<!DOCTYPE html>
<html lang="en" dir="ltr">

<head prefix="og: http://ogp.me/ns#">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>《Mastering Ethereum》笔记及EVM字节码逆向 – ruokeqx&#39;s blog</title>
    


  
  <script defer src="/js/fuse.min.8dfbf8696f107ab8b55732efbb04c5c51576692a4a2cce6effef9f6e92d341a7.js"></script>



<script src="/js/enquire.min.aa37bdcb743826eecdae5c5d177fc7d6552340f1b4378ffaa9c82b2c6111400b.js"></script>

<script defer src="/js/lazysizes.min.498676c34eb225e85357ab0ce19c3c1244f3bd0bf595e5684d1b9d50ea4fbc42.js"></script>

<script defer src="/js/helper/getParents.min.b75dda22e2d1c0e1e0574c7764bb95bec70c0fb0d4d5440339ba68c685d5a661.js"></script>

<script defer src="/js/helper/fadeinout.min.b1a8c6db3f3cc261756044570d21596f0f083625d41433dc9ac02aba5e53777b.js"></script>

<script defer src="/js/helper/closest.min.js"></script>
  
<script>
  "use strict";

  
  
  if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
  }

  
  if (!String.prototype.includes) {
    String.prototype.includes = function (search, start) {
      'use strict';

      if (search instanceof RegExp) {
        throw TypeError('first argument must not be a RegExp');
      }
      if (start === undefined) { start = 0; }
      return this.indexOf(search, start) !== -1;
    };
  }

  
  Document.prototype.append = Element.prototype.append = function append() {
    this.appendChild(_mutation(arguments));
  };
  function _mutation(nodes) {
    if (!nodes.length) {
      throw new Error('DOM Exception 8');
    } else if (nodes.length === 1) {
      return typeof nodes[0] === 'string' ? document.createTextNode(nodes[0]) : nodes[0];
    } else {
      var
      fragment = document.createDocumentFragment(),
      length = nodes.length,
      index = -1,
      node;

      while (++index < length) {
        node = nodes[index];

        fragment.appendChild(typeof node === 'string' ? document.createTextNode(node) : node);
      }

      return fragment;
    }
  }

  
  if (!String.prototype.startsWith) {
    String.prototype.startsWith = function (searchString, position) {
      position = position || 0;
      return this.indexOf(searchString, position) === position;
    };
  }
  


  document.addEventListener('DOMContentLoaded', function () {
    
    var navCollapseBtn = document.querySelector('.navbar__burger');
    navCollapseBtn ? navCollapseBtn.addEventListener('click', function (e) {
      var navCollapse = document.querySelector('.navbarm__collapse');

      if (navCollapse) {
        var dataOpen = navCollapse.getAttribute('data-open');

        if (dataOpen === 'true') {
          navCollapse.setAttribute('data-open', 'false');
          navCollapse.style.maxHeight = 0;
          navCollapseBtn.classList.remove('is-active');
        } else {
          navCollapse.setAttribute('data-open', 'true');
          navCollapse.style.maxHeight = navCollapse.scrollHeight + "px";
          navCollapseBtn.classList.add('is-active');
        }
      }
    }) : null;
    


    
    var tables = document.querySelectorAll('.single__contents > table');
    for (let i = 0; i < tables.length; i++) {
      var table = tables[i];
      var wrapper = document.createElement('div');
      wrapper.className = 'table-wrapper';
      table.parentElement.replaceChild(wrapper, table);
      wrapper.appendChild(table);
    }
    


    
    var footNoteRefs = document.querySelectorAll('.footnote-ref');
    var footNoteBackRefs = document.querySelectorAll('.footnote-backref');

    footNoteRefs ? 
    footNoteRefs.forEach(function(elem, idx) {
      elem.onmouseenter = function () {
        if (navbar.classList.contains('scrolling')) {
          navbar.classList.remove('scrolling');
        }
      }

      elem.onmouseleave = function () {
        if (!navbar.classList.contains('scrolling')) {
          setTimeout(function () {
            navbar.classList.add('scrolling');
          }, 100);
        }
      }

      elem.onclick = function () {
        if (!navbar.classList.contains('scrolling')) {
          navbar.classList.remove('navbar--show');
          navbar.classList.remove('navbar--hide');
          navbar.classList.add('navbar--hide');
        }
      }
    }) : null;

    footNoteBackRefs ? 
    footNoteBackRefs.forEach(function(elem, idx) {
      elem.onmouseenter = function () {
        if (navbar.classList.contains('scrolling')) {
          navbar.classList.remove('scrolling');
        }
      }

      elem.onmouseleave = function () {
        if (!navbar.classList.contains('scrolling')) {
          setTimeout(function() {
            navbar.classList.add('scrolling');
          }, 100);
        }
      }

      elem.onclick = function () {
        if (!navbar.classList.contains('scrolling')) {
          navbar.classList.remove('navbar--show');
          navbar.classList.remove('navbar--hide');
          navbar.classList.add('navbar--hide');
        }
      }
    }) : null;
    


    
    var summaryContainer = document.querySelector('.summary__container');
    var searchResult = document.querySelector('.search-result');
    var searchResultCloseBtn = document.querySelector('.search-result__close');
    searchResultCloseBtn ? searchResultCloseBtn.addEventListener('click', function (e) {
      searchResult.setAttribute('data-display', 'none');
      summaryContainer.setAttribute('data-display', 'block');
    }) : null;
    


    
    document.querySelectorAll('.tab') ? 
    document.querySelectorAll('.tab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var tabLinks = elem.querySelectorAll('.tab__link');
      var tabContents = elem.querySelectorAll('.tab__content');
      var ids = [];

      tabLinks && tabLinks.length > 0 ?
      tabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                tabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              tabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    document.querySelectorAll('.codetab') ? 
    document.querySelectorAll('.codetab').forEach(function(elem, idx) {
      var containerId = elem.getAttribute('id');
      var containerElem = elem;
      var codetabLinks = elem.querySelectorAll('.codetab__link');
      var codetabContents = elem.querySelectorAll('.codetab__content');
      var ids = [];

      codetabLinks && codetabLinks.length > 0 ?
      codetabLinks.forEach(function(link, index, self) {
        link.onclick = function(e) {
          for (var i = 0; i < self.length; i++) {
            if (index === parseInt(i, 10)) {
              if (!self[i].classList.contains('active')) {
                self[i].classList.add('active');
                codetabContents[i].style.display = 'block';
              }
            } else {
              self[i].classList.remove('active');
              codetabContents[i].style.display = 'none';
            }
          }
        }
      }) : null;
    }) : null;
    


    
    var gttBtn = document.getElementById("gtt");
    gttBtn.style.display = "none";
    gttBtn.addEventListener('click', function () {
      if (window.document.documentMode) {
        document.documentElement.scrollTop = 0;
      } else {
        scrollToTop(250);
      }
    });

    function scrollToTop(scrollDuration) {
      var scrollStep = -window.scrollY / (scrollDuration / 15);
      var scrollInterval = setInterval(function () {
        if (window.scrollY != 0) {
          window.scrollBy(0, scrollStep);
        }
        else clearInterval(scrollInterval);
      }, 15);
    }

    var scrollFunction = function () {
      if (document.body.scrollTop > 250 || document.documentElement.scrollTop > 250) {
        gttBtn.style.display = "block";
      } else {
        gttBtn.style.display = "none";
      }
    }
    


    
    var expandBtn = document.querySelectorAll('.expand__button');

    for (let i = 0; i < expandBtn.length; i++) {
      expandBtn[i].addEventListener("click", function () {
        var content = this.nextElementSibling;
        if (content.style.maxHeight) {
          content.style.maxHeight = null;
          this.querySelector('svg').classList.add('expand-icon__right');
          this.querySelector('svg').classList.remove('expand-icon__down');
        } else {
          content.style.maxHeight = content.scrollHeight + "px";
          this.querySelector('svg').classList.remove('expand-icon__right');
          this.querySelector('svg').classList.add('expand-icon__down');
        }
      });
    }
    


    
    var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
    var tocElem = document.querySelector('.toc');
    var tableOfContentsElem = tocElem ? tocElem.querySelector('#TableOfContents') : null;
    var toggleTocElem = document.getElementById('toggle-toc');
    var singleContentsElem = document.querySelector('.single__contents');
    var navbar = document.querySelector('.navbar');
    var tocFlexbox = document.querySelector('.toc__flexbox');
    var tocFlexboxOuter = document.querySelector('.toc__flexbox--outer');
    var expandContents = document.querySelectorAll('.expand__content');
    var boxContents = document.querySelectorAll('.box');
    var notAllowedTitleIds = null;

    
    var tocFolding = JSON.parse("true");
    
    var tocLevels = JSON.parse("[\"h2\",\"h3\",\"h4\",\"h5\"]");
    
    if (tocLevels) {
      tocLevels = tocLevels.toString();
    } else {
      tocLevels = "h1, h2, h3, h4, h5, h6";
    }

    
    singleContentsElem && singleContentsElem.querySelectorAll(".tab") ?
    singleContentsElem.querySelectorAll(".tab").forEach(function (elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    expandContents ? expandContents.forEach(function(elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    boxContents ? boxContents.forEach(function(elem) {
      elem.querySelectorAll(tocLevels).forEach(function (element) {
        notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
          notAllowedTitleIds.concat(element.getAttribute('id')) :
          [element.getAttribute('id')];
      });
    }) : null;

    
    window.onscroll = function () {
      scrollFunction();
      
      var st = window.pageYOffset || document.documentElement.scrollTop;
      if (st > lastScrollTop) { 
        if (st < 250) {
          gttBtn.style.display = "none";
        } else {
          gttBtn.style.display = "block";
        }

        if (st < 45) {
          return null;
        }

        if (navbar.classList.contains('scrolling')) {
          if (!navbar.classList.contains('navbar--hide')) {
            navbar.classList.add('navbar--hide');
          } else if (navbar.classList.contains('navbar--show')) {
            navbar.classList.remove('navbar--show');
          }
        }

        if (singleContentsElem) {
          if (singleContentsElem.querySelectorAll(tocLevels).length > 0) {
            singleContentsElem.querySelectorAll(tocLevels).forEach(function (elem) {
              if (toggleTocElem && !toggleTocElem.checked) {
                return null;
              }

              if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
                return null;
              }
              
              if (document.documentElement.scrollTop >= elem.offsetTop) {
                if (tableOfContentsElem) {
                  var id = elem.getAttribute('id');
                  tocElem.querySelectorAll('a').forEach(function (elem) {
                    elem.classList.remove('active');
                  });
                  tocElem.querySelector('a[href="#' + id + '"]') ?
                    tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;

                  if (false === tocFolding) {
                    
                  } else {
                    tableOfContentsElem.querySelectorAll('ul') ?
                      tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
                        rootUl.querySelectorAll('li').forEach(function (liElem) {
                          liElem.querySelectorAll('ul').forEach(function (ulElem) {
                            ulElem.style.display = 'none';
                          });
                        });
                      }) : null;
                  }

                  var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
                  if (curElem && curElem.nextElementSibling) {
                    curElem.nextElementSibling.style.display = 'block';
                  }
                  getParents(curElem, 'ul') ?
                    getParents(curElem, 'ul').forEach(function (elem) {
                      elem.style.display = 'block';
                    }) : null;
                }
              }
            });
          } else {
            if (tocFlexbox) {
              tocFlexbox.setAttribute('data-position', '');
              if (!tocFlexbox.classList.contains('hide')) {
                tocFlexbox.classList.add('hide');
              }
            }
            if (tocFlexboxOuter) {
              tocFlexboxOuter.setAttribute('data-position', '');
              if (!tocFlexboxOuter.classList.contains('hide')) {
                tocFlexboxOuter.classList.add('hide');
              }
            }
          }
        }
      } else { 
        if (st < 250) {
          gttBtn.style.display = "none";
        }

        if (navbar.classList.contains('scrolling')) {
          if (navbar.classList.contains('navbar--hide')) {
            navbar.classList.remove('navbar--hide');
          } else if (!navbar.classList.contains('navbar--show')) {
            navbar.classList.add('navbar--show');
          }
        }

        if (singleContentsElem) {
          if (singleContentsElem.querySelectorAll(tocLevels).length > 0) {
            singleContentsElem.querySelectorAll(tocLevels).forEach(function (elem) {
              if (toggleTocElem && !toggleTocElem.checked) {
                return null;
              }
              
              if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
                return null;
              }

              if (document.documentElement.scrollTop >= elem.offsetTop) {
                if (tableOfContentsElem) {
                  var id = elem.getAttribute('id');
                  tocElem.querySelectorAll('a').forEach(function (elem) {
                    elem.classList.remove('active');
                  });
                  tocElem.querySelector('a[href="#' + id + '"]') ?
                    tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;

                  if (false === tocFolding) {
                    
                  } else {
                    tableOfContentsElem.querySelectorAll('ul') ?
                      tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
                        rootUl.querySelectorAll('li').forEach(function (liElem) {
                          liElem.querySelectorAll('ul').forEach(function (ulElem) {
                            ulElem.style.display = 'none';
                          });
                        });
                      }) : null;
                  }

                  var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
                  if (curElem && curElem.nextElementSibling) {
                    curElem.nextElementSibling.style.display = 'block';
                  }
                  getParents(curElem, 'ul') ?
                    getParents(curElem, 'ul').forEach(function (elem) {
                      elem.style.display = 'block';
                    }) : null;
                }
              }
            });
          } else {
            if (tocFlexbox && !tocFlexbox.classList.contains('hide')) {
              tocFlexbox.classList.add('hide');
            }
            if (tocFlexboxOuter && !tocFlexboxOuter.classList.contains('hide')) {
              tocFlexboxOuter.classList.add('hide');
            }
          }
          
        }

        if (tableOfContentsElem && document.documentElement.scrollTop < 250) {
          if (false === tocFolding) {

          } else {
            tableOfContentsElem.querySelector('ul') ?
              tableOfContentsElem.querySelector('ul').querySelectorAll('li').forEach(function (liElem) {
                liElem.querySelectorAll('ul').forEach(function (ulElem) {
                  ulElem.style.display = 'none';
                });
              }) : null;
          }
        }
      }
      lastScrollTop = st <= 0 ? 0 : st;
    };
  


  
    var localTheme = localStorage.getItem('theme');
    var rootEleme = document.getElementById('root');
    var selectThemeElem = document.querySelectorAll('.select-theme');
    var selectThemeItemElem = document.querySelectorAll('.select-theme__item');
    
    
    var skinDarkCode = JSON.parse("\"dark\"");
    
    var skinLightCode = JSON.parse("\"light\"");
    
    var skinHackerCode = JSON.parse("\"hacker\"");
    
    var skinSolarizedCode = JSON.parse("\"solarized\"");
    
    var skinKimbieCode = JSON.parse("\"kimbie\"");

    var setMetaColor = function(themeColor) {
      var metaMsapplicationTileColor = document.getElementsByName('msapplication-TileColor')[0];
      var metaThemeColor = document.getElementsByName('theme-color')[0];
      var metaMsapplicationNavbuttonColor = document.getElementsByName('msapplication-navbutton-color')[0];
      var metaAppleMobileWebAappStatusBarStyle = document.getElementsByName('apple-mobile-web-app-status-bar-style')[0];

      if (themeColor.includes('dark')) {
        metaMsapplicationTileColor.setAttribute('content', '#fcfcfa');
        metaThemeColor.setAttribute('content', '#403E41');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#403E41');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#403E41');
      } else if (themeColor.includes('light')) {
        metaMsapplicationTileColor.setAttribute('content', '#555');
        metaThemeColor.setAttribute('content', '#eee');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#eee');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#eee');
      } else if (themeColor.includes('hacker')) {
        metaMsapplicationTileColor.setAttribute('content', '#e3cd26');
        metaThemeColor.setAttribute('content', '#252526');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#252526');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#252526');
      } else if (themeColor.includes('solarized')) {
        metaMsapplicationTileColor.setAttribute('content', '#d3af86');
        metaThemeColor.setAttribute('content', '#51412c');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#51412c');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#51412c');
      } else if (themeColor.includes('kimbie')) {
        metaMsapplicationTileColor.setAttribute('content', '#586e75');
        metaThemeColor.setAttribute('content', '#eee8d5');
        metaMsapplicationNavbuttonColor.setAttribute('content', '#eee8d5');
        metaAppleMobileWebAappStatusBarStyle.setAttribute('content', '#eee8d5');
      }
    }

    var parseSkinCode = function(themeText) {
      if (themeText === skinDarkCode) {
        return 'dark';
      } else if (themeText === skinLightCode) {
        return 'light';
      } else if (themeText === skinHackerCode) {
        return 'hacker';
      } else if (themeText === skinSolarizedCode) {
        return 'solarized';
      } else if (themeText === skinKimbieCode) {
        return 'kimbie';
      }
    }
    
    if (localTheme) {
      selectThemeItemElem ? 
      selectThemeItemElem.forEach(function (elem) {
        if (elem.text.trim() === localTheme) {
          elem.classList.add('is-active');
        } else {
          elem.classList.remove('is-active');
        }
      }) : null;

      setMetaColor(localTheme);
    } else {
      setMetaColor(rootEleme.className);
    }

    selectThemeItemElem ? 
    selectThemeItemElem.forEach(function (v, i) {
      v.addEventListener('click', function (e) {
        var selectedThemeVariant = parseSkinCode(e.target.text.trim());
        localStorage.setItem('theme', selectedThemeVariant);
        setMetaColor(selectedThemeVariant);

        rootEleme.removeAttribute('class');
        rootEleme.classList.add('theme__' + selectedThemeVariant);
        selectThemeElem.forEach(function(rootElem) {
          rootElem.querySelectorAll('a').forEach(function (elem) {
            if (elem.classList) {
              if (elem.text.trim() === selectedThemeVariant) {
                if (!elem.classList.contains('is-active')) {
                  elem.classList.add('is-active');
                }
              } else {
                if (elem.classList.contains('is-active')) {
                  elem.classList.remove('is-active');
                }
              }
            }
          });
        });

        if (window.mermaid) {
          if (selectedThemeVariant === "dark" || selectedThemeVariant === "hacker") {
            mermaid.initialize({ theme: 'dark' });
            location.reload();
          } else {
            mermaid.initialize({ theme: 'default' });
            location.reload();
          }
        }

        var utterances = document.getElementById('utterances');
        if (utterances) {
          utterances.querySelector('iframe').contentWindow.postMessage({
            type: 'set-theme',
            theme: selectedThemeVariant === "dark" || selectedThemeVariant === "hacker" ? 'photon-dark' : selectedThemeVariant === 'kimbie' ? 'github-dark-orange' : 'github-light',
          }, 'https://utteranc.es');
        }

        var twitterCards = document.querySelectorAll('.twitter-timeline');
        if (twitterCards) {
          window.postMessage({
            type: 'set-twitter-theme',
            theme: selectedThemeVariant === 'light' || selectedThemeVariant === 'solarized' ? 'light' : 'dark',
          });
        }
      });
    }) : null;
  


  
    
    var baseurl = JSON.parse("\"https://ruokeqx.gitee.io\"");
    
    var permalink = JSON.parse("\"https://ruokeqx.gitee.io/posts/ethereum101/\"");
    
    var langprefix = JSON.parse("\"\"");
    var searchResults = null;
    var searchMenu = null;
    var searchText = null;
    
    
    var enableSearch = JSON.parse("true");
    
    var searchDistance = JSON.parse("100");
    
    var searchThreshold = JSON.parse("0.4");
    
    var searchContent = JSON.parse("true");
    
    var enableSearchHighlight = JSON.parse("true");
    
    var searchResultPosition = JSON.parse("\"main\"");
    
    var sectionType = JSON.parse("\"posts\"");
    
    var kind = JSON.parse("\"page\"");
    
    var fuse = null;

    if (enableSearch) {
      (function initFuse() {
        var xhr = new XMLHttpRequest();
        if (sectionType === "publication" && kind !== "page") {
          xhr.open('GET', permalink + "index.json");
        } else {
          xhr.open('GET', baseurl + langprefix + "/index.json");
        }
        
        xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
        xhr.onload = function () {
          if (xhr.status === 200) {
            fuse = new Fuse(JSON.parse(xhr.response.toString('utf-8')), {
              keys: sectionType.includes('publication') ? ['title', 'abstract'] : 
                searchContent ? ['title', 'description', 'content'] : ['title', 'description'],
              includeMatches: enableSearchHighlight,
              shouldSort: true, 
              threshold: searchThreshold ? searchThreshold : 0.4, 
              location: 0, 
              distance: searchDistance ? searchDistance : 100, 
              maxPatternLength: 32,
              minMatchCharLength: 1,
              isCaseSensitive: false, 
              findAllMatches: false, 
              useExtendedSearch: false, 
            });
            window.fuse = fuse;
          }
          else {
            console.error('[' + xhr.status + ']Error:', xhr.statusText);
          }
        };
        xhr.send();
      })();
    }

    function makeLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      
      var a = document.createElement('a');
      a.innerHTML = obj.item.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.item.uri);

      var descDiv = document.createElement('div');
      descDiv.setAttribute('class', 'search-result__item--desc');
      if (obj.item.description) {
        descDiv.innerHTML = obj.item.description;
      } else if (obj.item.content) {
        descDiv.innerHTML = obj.item.content.substring(0, 225);
      }
      
      li.appendChild(a);
      li.appendChild(descDiv);
      ulElem.appendChild(li);
    }

    function makeHighlightLi(ulElem, obj) {
      var li = document.createElement('li');
      li.className = 'search-result__item';
      var descDiv = null;

      var a = document.createElement('a');
      a.innerHTML = obj.item.title;
      a.setAttribute('class', 'search-result__item--title');
      a.setAttribute('href', obj.item.uri);

      if (obj.matches && obj.matches.length) {
        for (var i = 0; i < obj.matches.length; i++) {
          if ('title' === obj.matches[i].key) {
            a = document.createElement('a');
            a.innerHTML = generateHighlightedText(obj.matches[i].value, obj.matches[i].indices);
            a.setAttribute('class', 'search-result__item--title');
            a.setAttribute('href', obj.item.uri);
          }
          
          if ('description' === obj.matches[i].key) {
            descDiv = document.createElement('div');
            descDiv.setAttribute('class', 'search-result__item--desc');
            descDiv.innerHTML = generateHighlightedText(obj.item.description, obj.matches[i].indices);
          } else if ('content' === obj.matches[i].key) {
            if (!descDiv) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = generateHighlightedText(obj.item.content.substring(0, 150), obj.matches[i].indices);
            }
          } else {
            if (obj.item.description) {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.description;
            } else {
              descDiv = document.createElement('div');
              descDiv.setAttribute('class', 'search-result__item--desc');
              descDiv.innerHTML = obj.item.content.substring(0, 150);
            }
          }
        }

        li.appendChild(a);
        if (descDiv) {
          li.appendChild(descDiv);
        }
        if (li) {
          ulElem.appendChild(li);
        }
      }
    }

    function renderSearchResultsSide(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dropdown is-active');
      
      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dropdown-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          a.setAttribute('href', result.uri);
          a.setAttribute('class', 'dropdown-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.title;
          titleDiv.setAttribute('class', 'menu-item__title');

          var descDiv = document.createElement('div');
          descDiv.setAttribute('class', 'menu-item__desc');
          if (result.description) {
            descDiv.innerHTML = result.description;
          } else if (result.content) {
            descDiv.innerHTML = result.content.substring(0, 150);
          }

          li.appendChild(titleDiv);
          li.appendChild(descDiv);
          ul.appendChild(a);
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dropdown-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      
      searchMenu.appendChild(ul);
    }

    function renderSearchHighlightResultsSide(searchText, results) {
      searchResults = document.getElementById('search-results');
      searchMenu = document.getElementById('search-menu');
      searchResults.setAttribute('class', 'dropdown is-active');

      var ul = document.createElement('ul');
      ul.setAttribute('class', 'dropdown-content search-content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.setAttribute('class', 'dropdown-item');
          a.appendChild(li);

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'menu-item__title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'menu-item__desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'menu-item__desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var li = document.createElement('li');
        li.setAttribute('class', 'dropdown-item');
        li.innerText = 'No results found';
        ul.appendChild(li);
      }

      while (searchMenu.hasChildNodes()) {
        searchMenu.removeChild(
          searchMenu.lastChild
        );
      }
      searchMenu.appendChild(ul);
    }

    function renderSearchResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var content = document.createElement('div');
      content.setAttribute('class', 'mobile-search__content');

      if (results.length > 0) {
        results.forEach(function (result) {
          var item = document.createElement('a');
          item.setAttribute('href', result.uri);
          item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + result.title + '</div><div class="mobile-search__item--desc">' + (result.description ? result.description : result.content) + '</div></div>';
          content.appendChild(item);
        });
      } else {
        var item = document.createElement('span');
        content.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(content);      
    }

    function renderSearchHighlightResultsMobile(searchText, results) {
      searchResults = document.getElementById('search-mobile-results');

      var ul = document.createElement('div');
      ul.setAttribute('class', 'mobile-search__content');

      if (results.length) {
        results.forEach(function (result) {
          var li = document.createElement('li');
          var a = document.createElement('a');
          var descDiv = null;

          a.setAttribute('href', result.item.uri);
          a.appendChild(li);
          li.setAttribute('class', 'mobile-search__item');

          var titleDiv = document.createElement('div');
          titleDiv.innerHTML = result.item.title;
          titleDiv.setAttribute('class', 'mobile-search__item--title');
          
          if (result.matches && result.matches.length) {
            for (var i = 0; i < result.matches.length; i++) {
              if ('title' === result.matches[i].key) {
                titleDiv.innerHTML = generateHighlightedText(result.matches[i].value, result.matches[i].indices);
              }

              if ('description' === result.matches[i].key) {
                descDiv = document.createElement('div');
                descDiv.setAttribute('class', 'mobile-search__item--desc');
                descDiv.innerHTML = generateHighlightedText(result.item.description, result.matches[i].indices);
              } else if ('content' === result.matches[i].key) {
                if (!descDiv) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = generateHighlightedText(result.item.content.substring(0, 150), result.matches[i].indices);
                }
              } else {
                if (result.item.description) {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.description;
                } else {
                  descDiv = document.createElement('div');
                  descDiv.setAttribute('class', 'mobile-search__item--desc');
                  descDiv.innerHTML = result.item.content.substring(0, 150);
                }
              }
            }
            
            li.appendChild(titleDiv);
            if (descDiv) {
              li.appendChild(descDiv);
            }
            ul.appendChild(a);
          }
        });
      } else {
        var item = document.createElement('span');
        ul.appendChild(item);
      }

      let wrap = document.getElementById('search-mobile-results');
      while (wrap.firstChild) {
        wrap.removeChild(wrap.firstChild)
      }
      searchResults.appendChild(ul);
    }

    function generateHighlightedText(text, regions) {
      if (!regions) {
        return text;
      }

      var content = '', nextUnhighlightedRegionStartingIndex = 0;

      regions.forEach(function(region) {
        if (region[0] === region[1]) {
          return null;
        }
        
        content += '' +
          text.substring(nextUnhighlightedRegionStartingIndex, region[0]) +
          '<span class="search__highlight">' +
            text.substring(region[0], region[1] + 1) +
          '</span>' +
        '';
        nextUnhighlightedRegionStartingIndex = region[1] + 1;
      });

      content += text.substring(nextUnhighlightedRegionStartingIndex);

      return content;
    };

    var searchElem = document.getElementById('search');
    var searchMobile = document.getElementById('search-mobile');
    var searchResultsContainer = document.getElementById('search-results');

    searchElem ?
    searchElem.addEventListener('input', function(e) {
      if (!e.target.value | window.innerWidth < 770) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      
      if (searchResultPosition === "main") {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsMain(searchText, results);
        } else {
          renderSearchResultsMain(searchText, results);
        }
      } else {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsSide(searchText, results);
        } else {
          renderSearchResultsSide(searchText, results);
        }
        
        var dropdownItems = searchResultsContainer.querySelectorAll('.dropdown-item');
        dropdownItems ? dropdownItems.forEach(function(item) {
          item.addEventListener('mousedown', function(e) {
            e.target.click();
          });
        }) : null;
      }
    }) : null;

    searchElem ? 
    searchElem.addEventListener('blur', function() {
      if (window.innerWidth < 770) {
        return null;
      }
      searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
    }) : null;

    searchElem ? 
    searchElem.addEventListener('click', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }
      if (!e.target.value) {
        searchResultsContainer ? searchResultsContainer.setAttribute('class', 'dropdown') : null;
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);

      if (searchResultPosition === "main") {
        if (enableSearchHighlight) {
          renderSearchHighlightResultsMain(searchText, results);
        } else {
          renderSearchResultsMain(searchText, results);
        }
      } else{
        if (enableSearchHighlight) {
          renderSearchHighlightResultsSide(searchText, results);
        } else {
          renderSearchResultsSide(searchText, results);
        }

        var dropdownItems = searchResultsContainer.querySelectorAll('.dropdown-item');
        dropdownItems ? dropdownItems.forEach(function (item) {
          item.addEventListener('mousedown', function (e) {
            e.target.click();
          });
        }) : null;
      }
    }) : null;

    var searchMenuElem = document.getElementById("search-menu");
    var activeItem = document.querySelector('#search-menu .dropdown-item.is-active');
    var activeIndex = null;
    var items = null;
    var searchContainerMaxHeight = 350;

    searchElem ? 
    searchElem.addEventListener('keydown', function(e) {
      if (window.innerWidth < 770) {
        return null;
      }

      if (e.key === 'Escape') {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      }

      var items = document.querySelectorAll('#search-menu .dropdown-item');
      var keyCode = e.which || e.keyCode;

      if (!items || !items.length) {
        return null;
      }
      
      if (e.key === 'ArrowDown' || keyCode === 40) {
        if (activeIndex === null) {
          activeIndex = 0;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
        }
        items[activeIndex].classList.add('is-active');

        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel > 0) {
          document.querySelector(".search-content").scrollTop += items[activeIndex].getBoundingClientRect().height;
        } else if (activeIndex === 0) {
          document.querySelector(".search-content").scrollTop = 0;
        }
      } else if (e.key === 'ArrowUp' || keyCode === 38) {
        if (activeIndex === null) {
          activeIndex = items.length - 1;
          items[activeIndex].classList.remove('is-active');
        } else {
          items[activeIndex].classList.remove('is-active');
          activeIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
        }
        items[activeIndex].classList.add('is-active');
        
        let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
        if (overflowedPixel < 0) {
          document.querySelector(".search-content").scrollTop -= items[activeIndex].getBoundingClientRect().height;
        } else {
          document.querySelector(".search-content").scrollTop = overflowedPixel + items[activeIndex].getBoundingClientRect().height;
        }
      } else if (e.key === 'Enter' || keyCode === 13) {
        if (items[activeIndex] && items[activeIndex].getAttribute('href')) {
          location.href = items[activeIndex].getAttribute('href');
        }
      } else if (e.key === 'Escape' || keyCode === 27) {
        e.target.value = null;
        if (searchResults) {
          searchResults.classList.remove('is-active');
        }
      }
    }) : null;

    searchMobile ? 
    searchMobile.addEventListener('input', function(e) {
      if (!e.target.value) {
        let wrap = document.getElementById('search-mobile-results');
        while (wrap.firstChild) {
          wrap.removeChild(wrap.firstChild);
        }
        return null;
      }

      searchText = e.target.value;
      var results = fuse.search(e.target.value);
      renderSearchResultsMobile(searchText, results);
      if (enableSearchHighlight) {
        renderSearchHighlightResultsMobile(searchText, results);
      } else {
        renderSearchResultsMobile(searchText, results);
      }
    }) : null;
  


  
    var mobileSearchInputElem = document.querySelector('#search-mobile');
    var mobileSearchClassElem = document.querySelector('.mobile-search');
    var mobileSearchBtnElems = document.querySelectorAll('.navbar-search');
    var mobileSearchCloseBtnElem = document.querySelector('#search-mobile-close');
    var mobileSearchContainer = document.querySelector('#search-mobile-container');
    var mobileSearchResultsElem = document.querySelector('#search-mobile-results');
    var htmlElem = document.querySelector('html');

    if (mobileSearchClassElem) {
      mobileSearchClassElem.style.display = 'none';
    }

    mobileSearchBtnElems ? 
    mobileSearchBtnElems.forEach(function (elem, idx) {
      elem.addEventListener('click', function () {
        if (mobileSearchContainer) {
          mobileSearchContainer.style.display = 'block';
        }

        if (mobileSearchInputElem) {
          mobileSearchInputElem.focus();
        }

        if (htmlElem) {
          htmlElem.style.overflowY = 'hidden';
        }
      });
    }) : null;

    mobileSearchCloseBtnElem ? 
    mobileSearchCloseBtnElem.addEventListener('click', function() {
      if (mobileSearchContainer) {
        mobileSearchContainer.style.display = 'none';
      }

      if (mobileSearchInputElem) {
        mobileSearchInputElem.value = '';
      }
      
      if (mobileSearchResultsElem) {
        while (mobileSearchResultsElem.firstChild) {
          mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
        }
      }

      if (htmlElem) {
        htmlElem.style.overflowY = 'visible';
      }
    }) : null;

    mobileSearchInputElem ?
    mobileSearchInputElem.addEventListener('keydown', function(e) {
      var keyCode = e.which || e.keyCode;
      if (e.key === 'Escape' || keyCode === 27) {
        if (mobileSearchContainer) {
          mobileSearchContainer.style.display = 'none';
        }
        
        if (mobileSearchInputElem) {
          mobileSearchInputElem.value = '';
        }

        if (mobileSearchResultsElem) {
          while (mobileSearchResultsElem.firstChild) {
            mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
          }
        }
        if (htmlElem) {
          htmlElem.style.overflowY = 'visible';
        }
      }
    }) : null;
  


  
    function renderSearchResultsMain(searchText, results) {
      var searchBody = document.querySelector('.search-result__body');
      var originUl = searchBody.querySelector('ul');
      var ul = document.createElement('ul');
      
      if (!searchText) {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      } else if (results) {
        if (results && results.length) {
          results.forEach(function (result) {
            makeLi(ul, result);
          });

          searchResult ? searchResult.setAttribute('data-display', 'block') : null;
          summaryContainer ? summaryContainer.setAttribute('data-display', 'none') : null;
        }
      }

      originUl.parentNode.replaceChild(ul, originUl);
    }

    function renderSearchHighlightResultsMain(searchText, results) {
      var searchBody = document.querySelector('.search-result__body');
      var originUl = searchBody.querySelector('ul');
      var ul = document.createElement('ul');

      if (!searchText) {
        searchResult ? searchResult.setAttribute('data-display', 'none') : null;
        summaryContainer ? summaryContainer.setAttribute('data-display', 'block') : null;
      } else if (results) {
        if (results && results.length) {
          results.forEach(function (result) {
            makeHighlightLi(ul, result);
          });

          searchResult ? searchResult.setAttribute('data-display', 'block') : null;
          summaryContainer ? summaryContainer.setAttribute('data-display', 'none') : null;
        }
      }

      originUl.parentNode.replaceChild(ul, originUl);
    }
  
  });
</script>
    
    


<link rel="stylesheet" href="/css/main.min.css">


    
<meta name="description" content="" />


<meta name="keywords" content="blockchain,ethereum">

<meta name="created" content="2022-05-22T00:00:00&#43;0000">
<meta name="modified" content="2022-05-22T00:00:00&#43;0000">
<meta property="article:published_time" content="2022-05-22T00:00:00&#43;0000">

<meta name="author" content="ruokeqx">


<meta property="og:site_name" content="ruokeqx&#39;s blog">
<meta property="og:title" content="《Mastering Ethereum》笔记及EVM字节码逆向">
<meta property="og:url" content="https://ruokeqx.gitee.io/posts/ethereum101/">
<meta property="og:type" content="article">
<meta property="og:description" content="">

<meta name="generator" content="Hugo 0.100.2" />
<meta name="msapplication-TileColor" content="#fff">

<meta name="theme-color" content="#fff">

<meta name="msapplication-navbutton-color" content="#fff">

<meta name="apple-mobile-web-app-status-bar-style" content="#fff">

<link rel="canonical" href="https://ruokeqx.gitee.io/posts/ethereum101/">

<link rel="manifest" href="/manifest.json">

  
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
  <link rel="icon" href="/favicon.png" sizes="any" type="image/png" />
  


    <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebPage",
    "headline": "《Mastering Ethereum》笔记及EVM字节码逆向",
    "datePublished": "2022-05-22T00:00:00Z",
    "dateModified": "2022-05-22T00:00:00Z",
    "url" : "https://ruokeqx.gitee.io/posts/ethereum101/",
    "description": "Background 机缘巧合，5-18面了某蓝厂web3\u0026amp;区块链部门，遂想了解一下web3\u0026amp;区块链。 看了一些视频，了解了Web3、DApp、D",
    "keywords": ["blockchain","ethereum"],
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://ruokeqx.gitee.io"
    },
    "publisher": {
      "@type": "Organization",
      "name": "ruokeqx's blog",
      "url": "https://ruokeqx.gitee.io"
    }
  }
</script>

    
  
  







  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    
</head>

<body id="root" class="theme__dark">
    <script>
        var localTheme = localStorage.getItem('theme');
        if (localTheme) {
            document.getElementById('root').className = 'theme__' + localTheme;
        }
    </script>
    <div id="container">
        





        <div class="wrapper" data-type="posts" data-kind="page">
            <nav class="navbar scrolling" role="navigation" aria-label="main navigation" data-dir="ltr">
  <div class="navbar__brand">
    
    <a href="/" title="Home" rel="home" class="navbar__logo-link">
      <img src="/logo.png" alt="Home" class="navbar__logo">
    </a>
    
    
      <a href="/" title="Home" rel="home" class="navbar__title-link">
        <h6 class="navbar__title">ruokeqx</h6>
      </a>
    
  </div>

  
<div class="theme theme-mobile" data-ani="true">
  <div class="dropdown">
    <button class="dropdown-trigger navbar__slide-down" aria-label="Select Theme Button" style="" data-ani="true">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M24 0H0v24h24V0z"/><path fill="currentColor" d="M6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58s4.1-.78 5.66-2.34c3.12-3.12 3.12-8.19 0-11.31l-4.95-4.95c-.39-.39-1.02-.39-1.41 0L6.34 7.93zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></svg>      
    </button>
    <div class="dropdown-content select-theme">
      
        
        <a href="#" class="dropdown-item select-theme__item is-active">
          dark
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          light
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          hacker
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          solarized
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          kimbie
        </a>
        
      
    </div>
  </div>
</div>


<div class="mobile-search__btn navbar-search" data-ani="true">
  <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
</div>

<div id="search-mobile-container" class="mobile-search hide" data-dir="ltr">
  <div class="mobile-search__top">
    <input id="search-mobile" type="text" aria-label="Mobile Search" placeholder="Search" class="mobile-search__top--input"/>
    <div id="search-mobile-close" class="mobile-search__top--icon">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path opacity=".87" fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z"/></svg>
    </div>
  </div>
  <div id="search-mobile-results" class="mobile-search__body">
    
  </div>
</div>


<a role="button" class="navbar__burger" aria-label="menu" aria-expanded="false"
  data-ani="true">
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
  <span aria-hidden="true"></span>
</a>
<div class="navbarm__collapse" data-open="false">
  <ul dir="ltr">
    
    
      
      
      
      

      
        <li class="navbarm__menu--item active">
          <a href="/posts">Posts</a>
        </li>
      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/archive">Archive</a>
        </li>
      
      
    
      
      
      
      

      
        <li class="navbarm__menu--item ">
          <a href="/about">About</a>
        </li>
      
      
    

    
      <li class="navbarm__menu--item ">
        <a href="/tags" class="navbarm__menu--term" data-index="0">
          Tags
        </a>
      </li>
    
      <li class="navbarm__menu--item ">
        <a href="/categories" class="navbarm__menu--term" data-index="1">
          Categories
        </a>
      </li>
    
      <li class="navbarm__menu--item ">
        <a href="/series" class="navbarm__menu--term" data-index="2">
          Series
        </a>
      </li>
    
  </ul>
</div>
  <div class="navbar__menu">
  
  
  
<div class="theme" data-ani="true">
  <div class="dropdown">
    <button class="dropdown-trigger navbar__slide-down" aria-label="Select Theme Button" data-ani="true">
      <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"><path fill="none" d="M24 0H0v24h24V0z"/><path fill="currentColor" d="M6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58s4.1-.78 5.66-2.34c3.12-3.12 3.12-8.19 0-11.31l-4.95-4.95c-.39-.39-1.02-.39-1.41 0L6.34 7.93zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></svg>      
    </button>
    <div class="dropdown-content select-theme">
      
        
        <a href="#" class="dropdown-item select-theme__item is-active">
          dark
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          light
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          hacker
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          solarized
        </a>
        
        <a href="#" class="dropdown-item select-theme__item ">
          kimbie
        </a>
        
      
    </div>
  </div>
</div>

  
  
  
  
  
  
  
  <a href="/posts" class="navbar__menu-item navbar__slide-down active" dir="ltr" data-ani="true">Posts</a>
  
  
  
  
  
  
  
  <a href="/archive" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">Archive</a>
  
  
  
  
  
  
  
  <a href="/about" class="navbar__menu-item navbar__slide-down " dir="ltr" data-ani="true">About</a>
  
  
</div>
</nav>
            
            

<main class="single__main main">
  
    <nav class="breadcrumb hide" aria-label="breadcrumbs">
  <script>document.querySelector('.breadcrumb').classList.remove('hide')</script>
  <ol>
    
  
  
  
  
  
  <li >
    
      <a href="https://ruokeqx.gitee.io/" class="capitalize">ruokeqx&#39;s blog</a>
    
  </li>
  
  
  <li >
    
      <a href="https://ruokeqx.gitee.io/posts/" class="capitalize">Posts</a>
    
  </li>
  
  
  <li  class="is-active" >
    
      <span>《Mastering Ethereum》笔记及EVM字节码逆向</span>
    
  </li>
  
  </ol>
  
</nav>
  
  
  <div class="single ">
    <div class="single__nojs">This page looks best with JavaScript enabled</div>
    <script>document.querySelector('.single').classList.remove('hide'); document.querySelector('.single__nojs').classList.add('hide');</script>
    <h2 class="single__title" data-ani="true">《Mastering Ethereum》笔记及EVM字节码逆向</h2>
    <h3 class="single__subtitle"></h3>
    <div class="single__meta">
      
<div class="single__infos">
  <time class="single__info" title="Written At">📅&nbsp;May 22, 2022 </time>
  
  &nbsp;&middot;&nbsp; <span class="single__info" title="Reading Time"> ☕&nbsp;8&nbsp;min read </span>
  
  <span class="single__info">
     &middot; 👀<span id="busuanzi_value_page_pv">...</span> views
  </span>
</div>

      
<ul class="single__tags caption">
  
  🏷️
  

  <li><a href="https://ruokeqx.gitee.io/tags/blockchain/" class="single__tag" title="blockchain">#blockchain</a></li>

  <li><a href="https://ruokeqx.gitee.io/tags/ethereum/" class="single__tag" title="ethereum">#ethereum</a></li>

</ul>

    </div>
    <article class="single__contents" data-dir="ltr" data-ani="true">
      
      <h2 id="background">Background</h2>
<p>机缘巧合，5-18面了某蓝厂web3&amp;区块链部门，遂想了解一下web3&amp;区块链。</p>
<p>看了一些视频，了解了Web3、DApp、DeFi、GameFi等概念。</p>
<p>两三天时间肝完了《Mastering Ethereum: Building Smart Contracts and DApps》。</p>
<p>了解了以太坊设计理念，钱包、交易、代币、预言机，安全策略，安全漏洞攻击方式及修复方式；对最新版本编译器生成的EVM字节码进行分析；发现并递交了书中出现的多个错误。</p>
<p>可以说是收获颇丰，写篇博客做下笔记和回顾。</p>
<h2 id="一what-is-ethereum">一、What is Ethereum</h2>
<p>Bitcoin: peer to peer cash system<br />
Ethereum: Smart contracts and DApps infrastructure</p>
<p>turing complete<br />
gas beat DOS</p>
<h2 id="二basic-concept">二、Basic concept</h2>
<pre tabindex="0"><code>单位
10**18 wei == 10**9 shannon(gigawei) == 1 ether
</code></pre><p>metamask ropsten faucet</p>
<h2 id="三客户端">三、客户端</h2>
<p>geth(go)<br />
parity(rust)<br />
json-rpc port 8545</p>
<h2 id="四密码学">四、密码学</h2>
<p>简单ECC&amp;ECDSA</p>
<p>以太坊地址：<br />
K(pub) = k(pri)*G<br />
addr = Keccak256(K)[-20:]</p>
<h2 id="五钱包">五、钱包</h2>
<p>钱包种子 助记词</p>
<h2 id="六交易">六、交易</h2>
<p>nonce<br />
gas price<br />
gas limit<br />
recipient<br />
value<br />
data<br />
v,r,s</p>
<p>递归长度前缀(RLP)编码</p>
<p>合约账户 外部账户<br />
合约创建地址0x0</p>
<h2 id="七solidity">七、Solidity</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># binary code</span>
</span></span><span class="line"><span class="cl">solc --optimize --bin Faucet.sol
</span></span><span class="line"><span class="cl">solc --abi Faucet.sol
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="c1">// SPDX-License-Identifier: CC-BY-SA-4.0
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">pragma solidity</span> <span class="mi">0</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">14</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// base contract
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">contract</span> <span class="nc">Owned</span>  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">address</span> <span class="k">payable</span> <span class="n">owner</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">constructor</span> <span class="p">(){</span>
</span></span><span class="line"><span class="cl">        <span class="n">owner</span> <span class="o">=</span> <span class="k">payable</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// function decorator
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">modifier</span> <span class="nf">onlyOwner</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// tx.origin unsafe
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span> <span class="o">==</span> <span class="n">owner</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">_</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// child contract
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">contract</span> <span class="nc">Mortal</span> <span class="k">is</span> <span class="n">Owned</span>  <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="c1">// Contract destructor
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="kd">function</span> <span class="nf">destroy</span><span class="p">()</span> <span class="k">public</span> <span class="n">onlyOwner</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nb">selfdestruct</span><span class="p">(</span><span class="n">owner</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">Faucet</span> <span class="k">is</span> <span class="n">Mortal</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// function FunctionName([parameters]) {public|private|internal|external}
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="c1">// [pure|view|payable] [modifiers] [returns (return types)]
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="kd">event</span> <span class="nc">Withdrawal</span><span class="p">(</span><span class="kt">address</span> <span class="k">indexed</span> <span class="n">to</span><span class="p">,</span> <span class="kt">uint</span> <span class="n">amount</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kd">event</span> <span class="nc">Deposit</span><span class="p">(</span><span class="kt">address</span> <span class="k">indexed</span> <span class="k">from</span><span class="p">,</span> <span class="kt">uint</span> <span class="n">amount</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Accept any incoming amount
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="n">receive</span><span class="p">()</span> <span class="k">external</span> <span class="k">payable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">emit</span> <span class="n">Deposit</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">,</span> <span class="nb">msg</span><span class="p">.</span><span class="nb">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Give out ether to anyone who asks
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">function</span> <span class="nf">withdraw</span><span class="p">(</span><span class="kt">uint</span> <span class="n">withdraw_amount</span><span class="p">)</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Limit withdrawal amount
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="n">withdraw_amount</span> <span class="o">&lt;=</span> <span class="mi">100000000000000000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span><span class="n">withdraw_amount</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">.</span><span class="mi">1</span> <span class="kc">ether</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="kt">address</span><span class="p">(</span><span class="nb">this</span><span class="p">).</span><span class="nb">balance</span> <span class="o">&gt;=</span> <span class="n">withdraw_amount</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s">&#34;Insufficient balance in faucet for withdrawal request&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Send the amount to the address that requested it
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">payable</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">).</span><span class="nb">transfer</span><span class="p">(</span><span class="n">withdraw_amount</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">emit</span> <span class="n">Withdrawal</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">,</span> <span class="n">withdraw_amount</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Some context
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// msg
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// tx
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// block
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// address
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="八vyper">八、Vyper</h2>
<p>内容比较少 认为也不是主要编写合约代码，看一个solidity够了 就没看</p>
<h2 id="九智能合约安全">九、智能合约安全</h2>
<h3 id="重入攻击">重入攻击</h3>
<p>漏洞点：<br />
line16 攻击方使用回调函数不断请求 然后维持的balances列表数据没有修改一直满足条件</p>
<p>修复：<br />
1.内置transfer函数(内部限制了2300gas) <br />
2.检查-生效-交互(把balances的修改放到调用之前)<br />
3.sol代码中使用互斥锁</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">EtherStore</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">withdrawalLimit</span> <span class="o">=</span> <span class="mi">1</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint256</span><span class="p">)</span> <span class="k">public</span> <span class="n">lastWithdrawTime</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint256</span><span class="p">)</span> <span class="k">public</span> <span class="n">balances</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">depositFunds</span><span class="p">()</span> <span class="k">external</span> <span class="k">payable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="nb">msg</span><span class="p">.</span><span class="nb">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">withdrawFunds</span><span class="p">(</span><span class="kt">uint256</span> <span class="n">_weiToWithdraw</span><span class="p">)</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span><span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">_weiToWithdraw</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// limit the withdrawal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="n">_weiToWithdraw</span> <span class="o">&lt;=</span> <span class="n">withdrawalLimit</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// limit the time allowed to withdraw
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="nb">block</span><span class="p">.</span><span class="nb">timestamp</span> <span class="o">&gt;=</span> <span class="n">lastWithdrawTime</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> <span class="kc">weeks</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">.</span><span class="nb">call</span><span class="p">{</span><span class="nb">value</span><span class="o">:</span> <span class="n">_weiToWithdraw</span><span class="p">}(</span><span class="s">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">-=</span> <span class="n">_weiToWithdraw</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">lastWithdrawTime</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">=</span> <span class="nb">block</span><span class="p">.</span><span class="nb">timestamp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="整型溢出">整型溢出</h3>
<p>漏洞点：<br />
line11 整型上溢 increaseLockTime(2**256-userLockTime) 上溢为0 就可以取出ether了</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">TimeLock</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint256</span><span class="p">)</span> <span class="k">public</span> <span class="n">balances</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint256</span><span class="p">)</span> <span class="k">public</span> <span class="n">lockTime</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">deposit</span><span class="p">()</span> <span class="k">external</span> <span class="k">payable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="nb">msg</span><span class="p">.</span><span class="nb">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">lockTime</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">=</span> <span class="nb">block</span><span class="p">.</span><span class="nb">timestamp</span> <span class="o">+</span> <span class="mi">1</span> <span class="kc">weeks</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">increaseLockTime</span><span class="p">(</span><span class="kt">uint256</span> <span class="n">_secondsToIncrease</span><span class="p">)</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">lockTime</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="n">_secondsToIncrease</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">withdraw</span><span class="p">()</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span><span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span><span class="nb">block</span><span class="p">.</span><span class="nb">timestamp</span> <span class="o">&gt;</span> <span class="n">lockTime</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint256</span> <span class="n">transferValue</span> <span class="o">=</span> <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">payable</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">).</span><span class="nb">transfer</span><span class="p">(</span><span class="n">transferValue</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>漏洞点：<br />
line14 15 整型下溢 0减去任何正整数都大于0</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="c1">// SPDX-License-Identifier: MIT
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">pragma solidity</span> <span class="o">^</span><span class="mi">0</span><span class="p">.</span><span class="mi">6</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">Token</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint</span><span class="p">)</span> <span class="n">balances</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">uint</span> <span class="k">public</span> <span class="n">totalSupply</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">constructor</span><span class="p">(</span><span class="kt">uint</span> <span class="n">_initialSupply</span><span class="p">)</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">=</span> <span class="n">totalSupply</span> <span class="o">=</span> <span class="n">_initialSupply</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">function</span> <span class="nf">transfer</span><span class="p">(</span><span class="kt">address</span> <span class="n">_to</span><span class="p">,</span> <span class="kt">uint</span> <span class="n">_value</span><span class="p">)</span> <span class="k">public</span> <span class="k">returns</span> <span class="p">(</span><span class="kt">bool</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">require</span><span class="p">(</span><span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">-</span> <span class="n">_value</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">balances</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">-=</span> <span class="n">_value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">balances</span><span class="p">[</span><span class="n">_to</span><span class="p">]</span> <span class="o">+=</span> <span class="n">_value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">function</span> <span class="nf">balanceOf</span><span class="p">(</span><span class="kt">address</span> <span class="n">_owner</span><span class="p">)</span> <span class="k">public</span> <span class="k">view</span> <span class="k">returns</span> <span class="p">(</span><span class="kt">uint</span> <span class="nb">balance</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">balances</span><span class="p">[</span><span class="n">_owner</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>修复：<br />
通常使用或构建安全算术运算的库合约来替代标准的算术加减</p>
<h3 id="unexpected-ether">Unexpected Ether</h3>
<ul>
<li>selfdestruct指令可以将合约摧毁并将余额传入指定地址</li>
<li>预先发送ether 合约地址通过 <code>address = sha3(rlp.encode([account_address,transaction_nonce]))</code> 计算 事先传入ether</li>
</ul>
<p>漏洞点：<br />
line 14 未预期的ether 传入非整数后 永远不可能等于10</p>
<p>修复：<br />
漏洞来源于对this.balance的依赖，完全可以新增一个变量追踪充值数额，这样就可以避免攻击</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">EtherGame</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">payoutMileStone1</span> <span class="o">=</span> <span class="mi">3</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">mileStone1Reward</span> <span class="o">=</span> <span class="mi">2</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">payoutMileStone2</span> <span class="o">=</span> <span class="mi">5</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">mileStone2Reward</span> <span class="o">=</span> <span class="mi">3</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">finalMileStone</span> <span class="o">=</span> <span class="mi">10</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint256</span> <span class="k">public</span> <span class="n">finalReward</span> <span class="o">=</span> <span class="mi">5</span> <span class="kc">ether</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">mapping</span><span class="p">(</span><span class="kt">address</span> <span class="o">=&gt;</span> <span class="kt">uint256</span><span class="p">)</span> <span class="n">redeemableEther</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Users pay 0.5 ether. At specific milestones, credit their accounts.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">function</span> <span class="nf">play</span><span class="p">()</span> <span class="k">external</span> <span class="k">payable</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nb">require</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">.</span><span class="mi">5</span> <span class="kc">ether</span><span class="p">);</span> <span class="c1">// each play is 0.5 ether
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="kt">uint256</span> <span class="n">currentBalance</span> <span class="o">=</span> <span class="kt">address</span><span class="p">(</span><span class="nb">this</span><span class="p">).</span><span class="nb">balance</span> <span class="o">+</span> <span class="nb">msg</span><span class="p">.</span><span class="nb">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// ensure no players after the game has finished
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="n">currentBalance</span> <span class="o">&lt;=</span> <span class="n">finalMileStone</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// if at a milestone, credit the player&#39;s account
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">if</span> <span class="p">(</span><span class="n">currentBalance</span> <span class="o">==</span> <span class="n">payoutMileStone1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="n">mileStone1Reward</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">currentBalance</span> <span class="o">==</span> <span class="n">payoutMileStone2</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="n">mileStone2Reward</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">currentBalance</span> <span class="o">==</span> <span class="n">finalMileStone</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">+=</span> <span class="n">finalReward</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">claimReward</span><span class="p">()</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// ensure the game is complete
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="kt">address</span><span class="p">(</span><span class="nb">this</span><span class="p">).</span><span class="nb">balance</span> <span class="o">==</span> <span class="n">finalMileStone</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// ensure there is a reward to give
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">require</span><span class="p">(</span><span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint256</span> <span class="n">transferValue</span> <span class="o">=</span> <span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">redeemableEther</span><span class="p">[</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">payable</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">).</span><span class="nb">transfer</span><span class="p">(</span><span class="n">transferValue</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十代币">十、代币</h2>
<p>ERC20、ERC721(NFT)</p>
<h2 id="十一预言机">十一、预言机</h2>
<p>预言机是一个可以回答以太坊外部问题的系统。<br />
设置预言机的三种主要方式可以分为 请求于响应、发布与订阅、立即读取。<br />
出于隐私考虑，可以在预言机上存储哈希而非原始数据。<br />
发布与订阅预期改变的数据，预言机要么由链上智能合约轮询(耗费gas)，要么由链外守护进程监视和更新(客户端的本地调用)。</p>
<h2 id="十二dapp">十二、DAPP</h2>
<p>IPFS、Swarm、Whisper</p>
<pre tabindex="0"><code>npm build
swarm --bzzapi http://localhost:8500 --recursive --defaultpath dist/index.html up dist/
</code></pre><p>ENS<br />
.eth顶级域名、拍卖域名、设置子域名、使用公共解析器、解析Swarm</p>
<h2 id="十三evm">十三、EVM</h2>
<p>基于栈的架构</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># opcodes(middle)</span>
</span></span><span class="line"><span class="cl">solc -o BytecodeDir --opcodes Example.sol
</span></span><span class="line"><span class="cl"><span class="c1"># detailed(max)</span>
</span></span><span class="line"><span class="cl">solc -o BytecodeDir --asm Example.sol
</span></span><span class="line"><span class="cl"><span class="c1"># bin(min)</span>
</span></span><span class="line"><span class="cl">solc -o BytecodeDir --bin Example.sol
</span></span></code></pre></td></tr></table>
</div>
</div><p>为尽量减少分析难度，编写了最简单的（没有汇入的可以说是错误的）水龙头代码，使用最新版本0.8.14（2022-05-21）solc编译获取字节码</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-solidity" data-lang="solidity"><span class="line"><span class="cl"><span class="k">pragma solidity</span> <span class="mi">0</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">14</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">contract</span> <span class="nc">Faucet</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nf">withdraw</span><span class="p">(</span><span class="kt">uint</span> <span class="n">withdraw_amount</span><span class="p">)</span> <span class="k">public</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nb">require</span><span class="p">(</span><span class="n">withdraw_amount</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">.</span><span class="mi">1</span> <span class="kc">ether</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">payable</span><span class="p">(</span><span class="nb">msg</span><span class="p">.</span><span class="nb">sender</span><span class="p">).</span><span class="nb">transfer</span><span class="p">(</span><span class="n">withdraw_amount</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>最初想尝试使用IDA-evm这个IDA插件进行分析，但是由于其仅支持python2，简单修复使其支持python3后发现并不能正常反编译出流程图</p>
<p>最后直接使用remix bytecode</p>
<p>代码分为代码段和数据段，代码段实际上是一个代码加载器，加载智能合约data中的数据，实际运行则是将数据段中数据移到0-len的位置，然后重入0开始运行，所以这是所有合约通用的加载器。</p>
<p>分析书上的版本编译器(0.6.x)生成的代码的时候发现许多愚蠢的指令 如下所示</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">PUSH1 0x0
</span></span><span class="line"><span class="cl">CALLDATASIZE
</span></span><span class="line"><span class="cl">PUSH29 0x100000... 
</span></span><span class="line"><span class="cl">SWAP1
</span></span><span class="line"><span class="cl">DIV
</span></span><span class="line"><span class="cl">PUSH4 0xffffffff
</span></span><span class="line"><span class="cl">AND
</span></span><span class="line"><span class="cl">DUP1
</span></span><span class="line"><span class="cl">PUSH4 0x2e1a7d4d
</span></span><span class="line"><span class="cl">EQ
</span></span><span class="line"><span class="cl">PUSH1 0x41
</span></span><span class="line"><span class="cl">JUMPI
</span></span></code></pre></td></tr></table>
</div>
</div><p>这段代码就是实现一个函数选择器的功能，先calldataload 然后push29 再 swap 这不是浪费gas吗，一个取对应函数选择器的代码这么多指令有很大优化空间，相比起来最新的编译器生成的代码使用位移SHR(看了一下字节码是0x1c之前是未使用的所以可能是新加的指令 又看了一下EIP145提出的 创建时间2017年很早了)就高效得多</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span><span class="lnt">159
</span><span class="lnt">160
</span><span class="lnt">161
</span><span class="lnt">162
</span><span class="lnt">163
</span><span class="lnt">164
</span><span class="lnt">165
</span><span class="lnt">166
</span><span class="lnt">167
</span><span class="lnt">168
</span><span class="lnt">169
</span><span class="lnt">170
</span><span class="lnt">171
</span><span class="lnt">172
</span><span class="lnt">173
</span><span class="lnt">174
</span><span class="lnt">175
</span><span class="lnt">176
</span><span class="lnt">177
</span><span class="lnt">178
</span><span class="lnt">179
</span><span class="lnt">180
</span><span class="lnt">181
</span><span class="lnt">182
</span><span class="lnt">183
</span><span class="lnt">184
</span><span class="lnt">185
</span><span class="lnt">186
</span><span class="lnt">187
</span><span class="lnt">188
</span><span class="lnt">189
</span><span class="lnt">190
</span><span class="lnt">191
</span><span class="lnt">192
</span><span class="lnt">193
</span><span class="lnt">194
</span><span class="lnt">195
</span><span class="lnt">196
</span><span class="lnt">197
</span><span class="lnt">198
</span><span class="lnt">199
</span><span class="lnt">200
</span><span class="lnt">201
</span><span class="lnt">202
</span><span class="lnt">203
</span><span class="lnt">204
</span><span class="lnt">205
</span><span class="lnt">206
</span><span class="lnt">207
</span><span class="lnt">208
</span><span class="lnt">209
</span><span class="lnt">210
</span><span class="lnt">211
</span><span class="lnt">212
</span><span class="lnt">213
</span><span class="lnt">214
</span><span class="lnt">215
</span><span class="lnt">216
</span><span class="lnt">217
</span><span class="lnt">218
</span><span class="lnt">219
</span><span class="lnt">220
</span><span class="lnt">221
</span><span class="lnt">222
</span><span class="lnt">223
</span><span class="lnt">224
</span><span class="lnt">225
</span><span class="lnt">226
</span><span class="lnt">227
</span><span class="lnt">228
</span><span class="lnt">229
</span><span class="lnt">230
</span><span class="lnt">231
</span><span class="lnt">232
</span><span class="lnt">233
</span><span class="lnt">234
</span><span class="lnt">235
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;functionDebugData&#34;</span>: <span class="o">{}</span>,
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;generatedSources&#34;</span>: <span class="o">[]</span>,
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;linkReferences&#34;</span>: <span class="o">{}</span>,
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;object&#34;</span>: <span class="s2">&#34;608060405234801561001057600080fd5b50610149806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80632e1a7d4d14610030575b600080fd5b61004a600480360381019061004591906100e6565b61004c565b005b67016345785d8a000081111561006157600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156100a7573d6000803e3d6000fd5b5050565b600080fd5b6000819050919050565b6100c3816100b0565b81146100ce57600080fd5b50565b6000813590506100e0816100ba565b92915050565b6000602082840312156100fc576100fb6100ab565b5b600061010a848285016100d1565b9150509291505056fea2646970667358221220e0ebfbb1f345e32e68dcacf4993ae16a9bd6a65a51698294e6c2094def89962564736f6c634300080e0033&#34;</span>,
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;opcodes&#34;</span>: <span class="s2">&#34;PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x149 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x2B JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x30 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x4A PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 PUSH2 0x45 SWAP2 SWAP1 PUSH2 0xE6 JUMP JUMPDEST PUSH2 0x4C JUMP JUMPDEST STOP JUMPDEST PUSH8 0x16345785D8A0000 DUP2 GT ISZERO PUSH2 0x61 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x8FC DUP3 SWAP1 DUP2 ISZERO MUL SWAP1 PUSH1 0x40 MLOAD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP9 DUP9 CALL SWAP4 POP POP POP POP ISZERO DUP1 ISZERO PUSH2 0xA7 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0xC3 DUP2 PUSH2 0xB0 JUMP JUMPDEST DUP2 EQ PUSH2 0xCE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 CALLDATALOAD SWAP1 POP PUSH2 0xE0 DUP2 PUSH2 0xBA JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xFC JUMPI PUSH2 0xFB PUSH2 0xAB JUMP JUMPDEST JUMPDEST PUSH1 0x0 PUSH2 0x10A DUP5 DUP3 DUP6 ADD PUSH2 0xD1 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xE0 0xEB 0xFB 0xB1 RETURN GASLIMIT 0xE3 0x2E PUSH9 0xDCACF4993AE16A9BD6 0xA6 GAS MLOAD PUSH10 0x8294E6C2094DEF899625 PUSH5 0x736F6C6343 STOP ADDMOD 0xE STOP CALLER &#34;</span>,
</span></span><span class="line"><span class="cl">	<span class="s2">&#34;sourceMap&#34;</span>: <span class="s2">&#34;25:181:0:-:0;;;;;;;;;;;;;;;;;;;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">.code
</span></span><span class="line"><span class="cl">  PUSH 80			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH 40			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  MSTORE 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  CALLVALUE 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  ISZERO 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH <span class="o">[</span>tag<span class="o">]</span> 1			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  JUMPI 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  REVERT 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">tag 1			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  JUMPDEST 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  POP 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH <span class="c1">#[$] 0000000000000000000000000000000000000000000000000000000000000000			contract Faucet {\r\n    funct...</span>
</span></span><span class="line"><span class="cl">  DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH <span class="o">[</span>$<span class="o">]</span> 0000000000000000000000000000000000000000000000000000000000000000			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  CODECOPY 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">  RETURN 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">.data
</span></span><span class="line"><span class="cl">  0:
</span></span><span class="line"><span class="cl">    .code
</span></span><span class="line"><span class="cl">      PUSH 80			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 40			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      MSTORE 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      CALLVALUE 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      ISZERO 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 1			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      JUMPI 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      REVERT 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">    tag 1			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      JUMPDEST 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      POP 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 4			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      CALLDATASIZE 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      LT 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 2			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      JUMPI 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      CALLDATALOAD 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH E0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      SHR 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 2E1A7D4D			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      EQ 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 3			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      JUMPI 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">    tag 2			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      JUMPDEST 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      PUSH 0			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      DUP1 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">      REVERT 			contract Faucet <span class="o">{</span><span class="se">\r\n</span>    funct...
</span></span><span class="line"><span class="cl">    tag 3			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMPDEST 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 4			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH 4			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      DUP1 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      CALLDATASIZE 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      SUB 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      DUP2 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      ADD 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      SWAP1 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 5			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      SWAP2 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      SWAP1 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 6			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMP 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">    tag 5			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMPDEST 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 7			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMP 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">    tag 4			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMPDEST 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      STOP 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">    tag 7			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMPDEST 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      PUSH 16345785D8A0000			0.1 ether
</span></span><span class="line"><span class="cl">      DUP2 			withdraw_amount
</span></span><span class="line"><span class="cl">      GT 			withdraw_amount &lt;<span class="o">=</span> 0.1 ether
</span></span><span class="line"><span class="cl">      ISZERO 			withdraw_amount &lt;<span class="o">=</span> 0.1 ether
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 9			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      JUMPI 			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      PUSH 0			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      DUP1 			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      REVERT 			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">    tag 9			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      JUMPDEST 			require<span class="o">(</span>withdraw_amount &lt;<span class="o">=</span> 0.1...
</span></span><span class="line"><span class="cl">      CALLER 			msg.sender
</span></span><span class="line"><span class="cl">      PUSH FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer
</span></span><span class="line"><span class="cl">      AND 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer
</span></span><span class="line"><span class="cl">      PUSH 8FC			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP3 			withdraw_amount
</span></span><span class="line"><span class="cl">      SWAP1 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP2 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      ISZERO 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      MUL 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      SWAP1 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH 40			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      MLOAD 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH 0			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH 40			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      MLOAD 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP1 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP4 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      SUB 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP2 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP6 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP9 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP9 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      CALL 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      SWAP4 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      ISZERO 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP1 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      ISZERO 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 11			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      JUMPI 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      RETURNDATASIZE 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH 0			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      DUP1 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      RETURNDATACOPY 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      RETURNDATASIZE 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      PUSH 0			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      REVERT 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">    tag 11			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      JUMPDEST 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			payable<span class="o">(</span>msg.sender<span class="o">)</span>.transfer<span class="o">(</span>w...
</span></span><span class="line"><span class="cl">      POP 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">      JUMP 			<span class="k">function</span> withdraw<span class="o">(</span>uint withdra...
</span></span><span class="line"><span class="cl">    tag 13			public <span class="o">{</span><span class="se">\r\n</span>      require<span class="o">(</span>with...
</span></span><span class="line"><span class="cl">      JUMPDEST 			public <span class="o">{</span><span class="se">\r\n</span>      require<span class="o">(</span>with...
</span></span><span class="line"><span class="cl">      PUSH 0			<span class="se">\n</span>
</span></span><span class="line"><span class="cl">      DUP1 			<span class="o">)</span>
</span></span><span class="line"><span class="cl">      REVERT 			_amount<span class="o">)</span><span class="p">;</span><span class="se">\r\n</span> 
</span></span><span class="line"><span class="cl">    tag 15			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      PUSH 0			
</span></span><span class="line"><span class="cl">      DUP2 			
</span></span><span class="line"><span class="cl">      SWAP1 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      SWAP2 			
</span></span><span class="line"><span class="cl">      SWAP1 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 16			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 24			
</span></span><span class="line"><span class="cl">      DUP2 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 15			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 24			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      DUP2 			
</span></span><span class="line"><span class="cl">      EQ 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 25			
</span></span><span class="line"><span class="cl">      JUMPI 			
</span></span><span class="line"><span class="cl">      PUSH 0			
</span></span><span class="line"><span class="cl">      DUP1 			
</span></span><span class="line"><span class="cl">      REVERT 			
</span></span><span class="line"><span class="cl">    tag 25			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 17			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      PUSH 0			
</span></span><span class="line"><span class="cl">      DUP2 			
</span></span><span class="line"><span class="cl">      CALLDATALOAD 			
</span></span><span class="line"><span class="cl">      SWAP1 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 27			
</span></span><span class="line"><span class="cl">      DUP2 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 16			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 27			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      SWAP3 			
</span></span><span class="line"><span class="cl">      SWAP2 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 6			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      PUSH 0			
</span></span><span class="line"><span class="cl">      PUSH 20			
</span></span><span class="line"><span class="cl">      DUP3 			
</span></span><span class="line"><span class="cl">      DUP5 			
</span></span><span class="line"><span class="cl">      SUB 			
</span></span><span class="line"><span class="cl">      SLT 			
</span></span><span class="line"><span class="cl">      ISZERO 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 29			
</span></span><span class="line"><span class="cl">      JUMPI 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 30			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 13			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 30			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">    tag 29			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      PUSH 0			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 31			
</span></span><span class="line"><span class="cl">      DUP5 			
</span></span><span class="line"><span class="cl">      DUP3 			
</span></span><span class="line"><span class="cl">      DUP6 			
</span></span><span class="line"><span class="cl">      ADD 			
</span></span><span class="line"><span class="cl">      PUSH <span class="o">[</span>tag<span class="o">]</span> 17			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    tag 31			
</span></span><span class="line"><span class="cl">      JUMPDEST 			
</span></span><span class="line"><span class="cl">      SWAP2 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      SWAP3 			
</span></span><span class="line"><span class="cl">      SWAP2 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      POP 			
</span></span><span class="line"><span class="cl">      JUMP 			
</span></span><span class="line"><span class="cl">    .data
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="十四consensus">十四、Consensus</h2>
<p>PoS(惩罚内生 失去Ether) vs PoW(惩罚外生 失去电费)<br />
Ethash:Ethereum PoW:依赖大型数据集(一个有向无环图 the DAG 难度线性增长 大型需频繁读取的数据结构 抗ASIC性 消费级GPU)的生成和分析<br />
Casper:Ethereum PoS</p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://github.com/ethereumbook/ethereumbook">https://github.com/ethereumbook/ethereumbook</a></li>
<li><a href="https://github.com/OpenZeppelin/ethernaut">https://github.com/OpenZeppelin/ethernaut</a></li>
<li><a href="https://sandbox.eth.build/">https://sandbox.eth.build/</a></li>
<li><a href="https://remix.ethereum.org/">https://remix.ethereum.org/</a></li>
</ul>

    </article>
    
    
<script defer src="/js/clipboard.min.c168d3a04c45a631be76437054619a4a3b30107960cb9730be96012fef5762b0.js"></script>

<script defer src="/js/helper/prev.min.js"></script>

<script defer src="/js/helper/prop.min.js"></script>
<script>
  'use strict';
  document.addEventListener('DOMContentLoaded', function () {
    
    var clipInit = false;
    var preChromaElem = document.querySelectorAll('pre.chroma');
    var langCodeElem = document.querySelectorAll('.language-code');
    var dollarCodeElem = document.querySelectorAll('div.language-\\$');
    var gtCodeElem = document.querySelectorAll('div.language-\\>');

    var makeClipboard = function(elem) {
      var code = elem,
          text = elem.textContent;
        
      if (text.length > 15) {
        if (!clipInit) {
          var text, clip = new ClipboardJS('.copy-to-clipboard', {
            text: function (trigger) {
              var codeElem = prev(trigger).querySelectorAll('code');
              if (codeElem.length > 1) {
                text = prev(trigger).querySelector('code[class^="language-"]').textContent;
              } else {
                text = prev(trigger).querySelector('code').textContent;
              }

              return text.replace(/^\$\s/gm, '');
            }
          });

          var inPre;
          clip.on('success', function (e) {
            e.clearSelection();
            inPre = prop(e.trigger.parentNode, 'tagName') == 'PRE';
            e.trigger.setAttribute('aria-label', 'Copied to clipboard!');
            e.trigger.classList.add('tooltipped');
            e.trigger.classList.add('tooltipped-w');
          });

          clip.on('error', function (e) {
            inPre = prop(e.trigger.parentNode, 'tagName') == 'PRE';
            e.trigger.setAttribute('aria-label', e.action.toString());
            e.trigger.classList.add('tooltipped');
            e.trigger.classList.add('tooltipped-w');
          });

          clipInit = true;
        }

        var notAllowedClass = ['language-mermaid', 'language-viz', 'language-wave', 'language-chart', 'language-msc', 'language-flowchart'];
        var isNotAllowedIncluded = false;
        var curClassName = code.getAttribute('class');

        for (var i = 0; i < notAllowedClass.length; i++) {
          if (curClassName && curClassName.startsWith(notAllowedClass[i])) {
            isNotAllowedIncluded = true;
            break;
          }
        }

        if (!isNotAllowedIncluded) {
          if (curClassName) {
            var newClipboardElem = document.createElement('span');
            newClipboardElem.setAttribute('class', 'copy-to-clipboard');
            newClipboardElem.setAttribute('title', 'Copy to clipboard');
            elem.parentNode.parentNode.insertBefore(newClipboardElem, elem.parentNode.nextElementSibling);
          }
        }
      }
    }

    var makeSymbolClipboard = function(elem) {
      var clipboardSpan = document.createElement('span');
      clipboardSpan.setAttribute('class', 'copy-to-clipboard');
      clipboardSpan.setAttribute('title', 'Copy to clipboard');
      elem.parentNode.parentNode.insertBefore(clipboardSpan, elem.parentNode.nextElementSibling);
    }

    preChromaElem ? 
    preChromaElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function(codeElem) {
        makeClipboard(codeElem);
      });
    }) : null;
    
    langCodeElem ? 
    langCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeClipboard(codeElem);
      });
    }) : null;

    dollarCodeElem ? 
    dollarCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeSymbolClipboard(codeElem);
      });
    }) : null;

    gtCodeElem ?
    gtCodeElem.forEach(function(elem) {
      elem.querySelectorAll('code').forEach(function (codeElem) {
        makeSymbolClipboard(codeElem);
      });
    }) : null;
    
  });
</script>
    <script>
  'use strict';
  
  function wrap(el, wrapper) {
    el.parentNode.insertBefore(wrapper, el);
    wrapper.appendChild(el);
  }

  (function () {
    var singleContentsElem = document.querySelector('.single__contents');
    singleContentsElem ? 
    singleContentsElem.querySelectorAll('pre > code').forEach(function(elem) {
      var dataLang = elem.getAttribute('data-lang');
      var dataLangWrapper = document.createElement('div');
      var code = null;
      var codeTitle = null;

      if (dataLang && dataLang.includes(':')) {
        code = dataLang.split(':')[0];
        codeTitle = dataLang.split(':')[1];

        dataLangWrapper.className = 'language-' + code;
        dataLangWrapper.setAttribute('data-lang', codeTitle);

        elem.className = 'language-' + code;
        elem.setAttribute('data-lang', codeTitle);
        elem.setAttribute('id', codeTitle);
      } else if (!dataLang) {
        dataLangWrapper.setAttribute('data-lang', 'Code');
        dataLangWrapper.className = 'language-code';
      }

      if (!dataLang || codeTitle) {
        wrap(elem.parentNode, dataLangWrapper);
      }

    }) : null;
  })();

  var langCodeElem = document.querySelectorAll('.language-code');
  langCodeElem ? langCodeElem.forEach(function (elem) {
    var newElem = document.createElement('span');
    newElem.className = 'copy-to-clipboard';
    newElem.setAttribute('title', 'Copy to clipboard');
    elem.append(newElem);
  }) : null;
  

  

  
  var dollarCodeElem = document.querySelectorAll('div.language-\\$');
  var gtCodeElem = document.querySelectorAll('div.language-\\>');

  dollarCodeElem ?
  dollarCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '$<br/>';
    }) : null;
  }) : null;

  gtCodeElem ?
  gtCodeElem.forEach(function(elem) {
    var lnts = elem.parentNode.parentNode ? elem.parentNode.parentNode.querySelectorAll('.lnt') : null;
    lnts ? 
    lnts.forEach(function(lnt) {
      lnt.innerHTML = '><br/>';
    }) : null;
  }) : null;
  
</script>
    
<div class="donation">
  <div class="donation__message">
    Share on
  </div>
  <div class="donation__icons">
    
    
    
      
    
      
    
  </div>
</div>


    
    
<div class="whoami__gutter"></div>
<hr class="hr-slash whoami-hr"/>
<section class="whoami">
  <div class="whoami__image-wrapper">
    
    
      
        <img data-src="/images/whoami/avatar.jpg" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" alt="ruokeqx" class="lazyload whoami__image"/>
      
    
  </div>
  <div class="whoami__contents">
    <div class="whoami__written-by">
      WRITTEN BY
    </div>
    <div class="whoami__title">
      
        ruokeqx
      
    </div>
    <div class="whoami__desc">
      
        
      
    </div>
    <div class="whoami__social">
      
      
      
      
      
      
      
      
      <a href="ruokeqx@163.com" title="email" aria-label="email">
        <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-.4 4.25l-7.07 4.42c-.32.2-.74.2-1.06 0L4.4 8.25c-.25-.16-.4-.43-.4-.72 0-.67.73-1.07 1.3-.72L12 11l6.7-4.19c.57-.35 1.3.05 1.3.72 0 .29-.15.56-.4.72z"/></svg>
      </a>
      
      
      
      
      
      
      
      <a href="https://github.com/ruokeqx" title="github" aria-label="github">
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 24 24" version="1.1">
<g id="surface3680">
<path fill="currentColor" d="M 10.898438 2.101562 C 6.300781 2.601562 2.601562 6.300781 2.101562 10.800781 C 1.601562 15.5 4.300781 19.699219 8.398438 21.300781 C 8.699219 21.398438 9 21.199219 9 20.800781 L 9 19.199219 C 9 19.199219 8.601562 19.300781 8.101562 19.300781 C 6.699219 19.300781 6.101562 18.101562 6 17.398438 C 5.898438 17 5.699219 16.699219 5.398438 16.398438 C 5.101562 16.300781 5 16.300781 5 16.199219 C 5 16 5.300781 16 5.398438 16 C 6 16 6.5 16.699219 6.699219 17 C 7.199219 17.800781 7.800781 18 8.101562 18 C 8.5 18 8.800781 17.898438 9 17.800781 C 9.101562 17.101562 9.398438 16.398438 10 16 C 7.699219 15.5 6 14.199219 6 12 C 6 10.898438 6.5 9.800781 7.199219 9 C 7.101562 8.800781 7 8.300781 7 7.601562 C 7 7.199219 7 6.601562 7.300781 6 C 7.300781 6 8.699219 6 10.101562 7.300781 C 10.601562 7.101562 11.300781 7 12 7 C 12.699219 7 13.398438 7.101562 14 7.300781 C 15.300781 6 16.800781 6 16.800781 6 C 17 6.601562 17 7.199219 17 7.601562 C 17 8.398438 16.898438 8.800781 16.800781 9 C 17.5 9.800781 18 10.800781 18 12 C 18 14.199219 16.300781 15.5 14 16 C 14.601562 16.5 15 17.398438 15 18.300781 L 15 20.898438 C 15 21.199219 15.300781 21.5 15.699219 21.398438 C 19.398438 19.898438 22 16.300781 22 12.101562 C 22 6.101562 16.898438 1.398438 10.898438 2.101562 Z M 10.898438 2.101562 "/>
</g>
</svg>

      </a>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </div>
  </div>
</section>
<hr class="hr-slash whoami-hr" />


    <section class="related">
    
    
  </section>
    <div class="grow"></div>
<nav class="pagination-single">
  
    
      <a href="https://ruokeqx.gitee.io/posts/libpcaptcpdumpkernel-net%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/" class="pagination-single__left">
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42-.39-.39-1.02-.39-1.41 0l-6.59 6.59c-.39.39-.39 1.02 0 1.41l6.59 6.59c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1z"/></svg>
        </div>
        <div class="pagination-single__left-title">libpcap、tcpdump以及kernel/net的部分源码阅读</div>      
      </a>
    
    <div class="grow"></div>
    
      <a href="https://ruokeqx.gitee.io/posts/bpf_uprobe_bypass_go_tls/" class="pagination-single__right">      
        <div class="pagination-single__right-title">eBPF Uprobe bypass Go tls——抓取https明文流量</div>
        <div class="pagination-single__icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M5 13h11.17l-4.88 4.88c-.39.39-.39 1.03 0 1.42.39.39 1.02.39 1.41 0l6.59-6.59c.39-.39.39-1.02 0-1.41l-6.58-6.6c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L16.17 11H5c-.55 0-1 .45-1 1s.45 1 1 1z"/></svg>
        </div>
      </a>
    
  
</nav>
    
    <div class="modal micromodal-slide" id="modal" aria-hidden="true">
  <div class="modal__overlay" tabindex="-1" data-micromodal-close>
    <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
      
      <div class="modal__content" id="modal-content">
        <div id="mySwipe" class="swipe">
          <div class="swipe-wrap">
          </div>
        </div>
      </div>

      <span class="modal__items">
        
        <span class="modal__header">
          <div class="modal__paging" title="Page Info" aria-label="Current Page">
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--close" title="Close" aria-label="Close Button" data-micromodal-close>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="25" height="25"><path fill="currentColor" d="M 21.734375 19.640625 L 19.636719 21.734375 C 19.253906 22.121094 18.628906 22.121094 18.242188 21.734375 L 13 16.496094 L 7.761719 21.734375 C 7.375 22.121094 6.746094 22.121094 6.363281 21.734375 L 4.265625 19.640625 C 3.878906 19.253906 3.878906 18.628906 4.265625 18.242188 L 9.503906 13 L 4.265625 7.761719 C 3.882813 7.371094 3.882813 6.742188 4.265625 6.363281 L 6.363281 4.265625 C 6.746094 3.878906 7.375 3.878906 7.761719 4.265625 L 13 9.507813 L 18.242188 4.265625 C 18.628906 3.878906 19.257813 3.878906 19.636719 4.265625 L 21.734375 6.359375 C 22.121094 6.746094 22.121094 7.375 21.738281 7.761719 L 16.496094 13 L 21.734375 18.242188 C 22.121094 18.628906 22.121094 19.253906 21.734375 19.640625 Z"/></svg>
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--full" title="Full Screen" aria-label="Full Screen Button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="25" height="25"><path fill="currentColor" d="M 5 3 C 3.9069372 3 3 3.9069372 3 5 L 3 8 A 1.0001 1.0001 0 1 0 5 8 L 5 5 L 8 5 A 1.0001 1.0001 0 1 0 8 3 L 5 3 z M 16 3 A 1.0001 1.0001 0 1 0 16 5 L 19 5 L 19 8 A 1.0001 1.0001 0 1 0 21 8 L 21 5 C 21 3.9069372 20.093063 3 19 3 L 16 3 z M 3.984375 14.986328 A 1.0001 1.0001 0 0 0 3 16 L 3 19 C 3 20.093063 3.9069372 21 5 21 L 8 21 A 1.0001 1.0001 0 1 0 8 19 L 5 19 L 5 16 A 1.0001 1.0001 0 0 0 3.984375 14.986328 z M 19.984375 14.986328 A 1.0001 1.0001 0 0 0 19 16 L 19 19 L 16 19 A 1.0001 1.0001 0 1 0 16 21 L 19 21 C 20.093063 21 21 20.093063 21 19 L 21 16 A 1.0001 1.0001 0 0 0 19.984375 14.986328 z"/></svg>
          </div>
          <div class="modal__icon modal__toolbar modal__toolbar--normal" title="Normal Screen" aria-label="Normal Screen Button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="25" height="25"><path fill="currentColor" d="M 16.96875 4.972656 C 15.867188 4.988281 14.984375 5.894531 15 7 L 15 15 L 7 15 C 6.277344 14.988281 5.609375 15.367188 5.246094 15.992188 C 4.878906 16.613281 4.878906 17.386719 5.246094 18.007813 C 5.609375 18.632813 6.277344 19.011719 7 19 L 19 19 L 19 7 C 19.007813 6.460938 18.796875 5.941406 18.414063 5.558594 C 18.03125 5.175781 17.511719 4.964844 16.96875 4.972656 Z M 32.96875 4.972656 C 31.921875 4.988281 31.0625 5.8125 31.003906 6.859375 C 31 6.90625 31 6.953125 31 7 L 31 19 L 43 19 C 43.066406 19 43.132813 19 43.199219 18.992188 C 44.269531 18.894531 45.070313 17.972656 45.015625 16.902344 C 44.964844 15.828125 44.074219 14.988281 43 15 L 35 15 L 35 7 C 35.007813 6.460938 34.796875 5.941406 34.414063 5.558594 C 34.03125 5.175781 33.511719 4.964844 32.96875 4.972656 Z M 7 31 C 6.277344 30.988281 5.609375 31.367188 5.246094 31.992188 C 4.878906 32.613281 4.878906 33.386719 5.246094 34.007813 C 5.609375 34.632813 6.277344 35.011719 7 35 L 15 35 L 15 43 C 14.988281 43.722656 15.367188 44.390625 15.992188 44.753906 C 16.613281 45.121094 17.386719 45.121094 18.007813 44.753906 C 18.632813 44.390625 19.011719 43.722656 19 43 L 19 31 Z M 31 31 L 31 43 C 30.988281 43.722656 31.367188 44.390625 31.992188 44.753906 C 32.613281 45.121094 33.386719 45.121094 34.007813 44.753906 C 34.632813 44.390625 35.011719 43.722656 35 43 L 35 35 L 43 35 C 43.722656 35.011719 44.390625 34.632813 44.753906 34.007813 C 45.121094 33.386719 45.121094 32.613281 44.753906 31.992188 C 44.390625 31.367188 43.722656 30.988281 43 31 Z"/></svg>
          </div>
        </span>
        
        <div class="modal__icon modal__arrow modal__arrow--left" title="Arrow Left" aria-label="Arrow Left Button">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="28" height="28"><path fill="currentColor" d="M 23.28125 11 L 10 10 L 10 6.851563 C 10 6.523438 9.839844 6.277344 9.519531 6.03125 C 9.199219 5.949219 8.878906 5.949219 8.640625 6.113281 C 5.359375 8.410156 2.238281 12.257813 2.160156 12.421875 C 2.082031 12.578125 2.007813 12.8125 2.003906 12.976563 C 2.003906 12.980469 2 12.988281 2 12.992188 C 2 13.15625 2.078125 13.402344 2.160156 13.484375 C 2.238281 13.648438 5.28125 17.507813 8.640625 19.804688 C 8.960938 19.96875 9.28125 20.050781 9.519531 19.886719 C 9.839844 19.722656 10 19.476563 10 19.148438 L 10 16 L 23.28125 15 C 23.679688 14.679688 24 13.875 24 12.992188 C 24 12.195313 23.761719 11.320313 23.28125 11 Z"/></svg>
        </div>
        
        <div class="modal__icon modal__arrow modal__arrow--right" title="Arrow Right" aria-label="Arrow Right Button">

          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26" width="28" height="28"><path fill="currentColor" d="M 2.71875 11.023438 L 16 10.023438 L 16 6.875 C 16 6.546875 16.160156 6.300781 16.480469 6.054688 C 16.800781 5.972656 17.121094 5.972656 17.359375 6.136719 C 20.640625 8.433594 23.761719 12.28125 23.839844 12.445313 C 23.917969 12.601563 23.992188 12.835938 23.996094 13 C 23.996094 13.003906 24 13.011719 24 13.015625 C 24 13.179688 23.921875 13.425781 23.839844 13.507813 C 23.761719 13.671875 20.71875 17.53125 17.359375 19.828125 C 17.039063 19.992188 16.71875 20.074219 16.480469 19.910156 C 16.160156 19.746094 16 19.5 16 19.171875 L 16 16.023438 L 2.71875 15.023438 C 2.320313 14.703125 2 13.898438 2 13.015625 C 2 12.21875 2.238281 11.34375 2.71875 11.023438 Z"/></svg>
        </div>

        <div class="modal__caption">
          <div class="modal__caption--text">
          </div>
        </div>

      </span>
    </div>
  </div>
</div>


<script defer src="/js/swipe.min.b5af2be70ffc9ba2e83412609aa18b5b025c69399f9e1dce09d444a636a38cd0.js"></script>

<script defer src="/js/micromodal.min.de01b44b2f383056bbcaf6ee921fd385d79108ec1129afd0eb2f3f5a07e11f45.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function () {
  
   
  var docElem = document.documentElement;

   
  function openFullscreen() {
    if (docElem.requestFullscreen) {
      docElem.requestFullscreen();
    } else if (docElem.mozRequestFullScreen) {  
      docElem.mozRequestFullScreen();
    } else if (docElem.webkitRequestFullscreen) {  
      docElem.webkitRequestFullscreen();
    } else if (docElem.msRequestFullscreen) {  
      docElem.msRequestFullscreen();
    }
  }

   
  function closeFullscreen() {
    if (document.fullscreenElement ||
      document.webkitFullscreenElement ||
      document.mozFullScreenElement) {
      if (document.exitFullscreen) {
        document.exitFullscreen();
      } else if (document.mozCancelFullScreen) {  
        document.mozCancelFullScreen();
      } else if (document.webkitExitFullscreen) {  
        document.webkitExitFullscreen();
      } else if (document.msExitFullscreen) {  
        document.msExitFullscreen();
      }
    }
  }

  var modal = document.getElementById('modal');
  var galleryContainerElem = document.querySelector('.gallery__container');
  var swipeWrapElem = document.querySelector('.swipe-wrap');
  var mySwipeElem = document.getElementById('mySwipe');
  var arrowLeftElem = document.querySelector('.modal__arrow--left');
  var arrowRightElem = document.querySelector('.modal__arrow--right');
  var closeElem = document.querySelector('.modal__toolbar--close');
  var fullElem = document.querySelector('.modal__toolbar--full');
  var normalElem = document.querySelector('.modal__toolbar--normal');
  var captionElem = document.querySelector('.modal__caption');
  var pagingElem = document.querySelector('.modal__paging');
  var itemsElem = document.querySelector('.modal__items');
  var imgTotalNum = null;
  var myFadeTimeout = null;
  var mySwipe = null;
  var keydownFunction = function (e) {
    if (e.key === 'ArrowRight') {
      if (modal && modal.classList.contains('is-open')) {
        mySwipe.next();
      }
    } else if (e.key === 'ArrowLeft') {
      if (modal && modal.classList.contains('is-open')) {
        mySwipe.prev();
      }
    }
  }

  if (galleryContainerElem) {
    imgTotalNum = galleryContainerElem.querySelectorAll('img').length;
  } else {
    galleryContainerElem = document.querySelector('.single__contents');
    imgTotalNum = galleryContainerElem.querySelectorAll('img').length;
  }

  MicroModal.init({
    onClose: function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
        closeFullscreen();
      }
      window.removeEventListener('keydown', keydownFunction);
    },
    disableScroll: true,
    disableFocus: true,
    awaitOpenAnimation: false,
    awaitCloseAnimation: false,
    debugMode: false,
  });

  var imageLoad = function(src) {
    return new Promise(function(resolve, reject) {
      var newImg = new Image;
      newImg.onload = function() {
        resolve(newImg);
      }
      newImg.onerror = reject;
      newImg.src = src;
    });
  }

  galleryContainerElem.querySelectorAll('img').forEach(function (elem, idx) {
    elem.style.cursor = 'pointer';

    var clonedElem = elem.cloneNode(true);
    clonedElem.style.maxHeight = '100%';
    clonedElem.style.maxWidth = '100%';
    clonedElem.onclick = function (e) {
      e.stopPropagation();
    }

    var wrapper = document.createElement('div');
    wrapper.style.width = '100%';
    wrapper.style.height = '100vh';
    wrapper.setAttribute('data-micromodal-close', '');
    wrapper.onclick = function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }
    }
    wrapper.onmouseenter = function () {
      clearTimeout(myFadeTimeout);
      fadeIn(itemsElem, 200);
    };
    wrapper.onmouseleave = function () {
      myFadeTimeout = setTimeout(function () {
        fadeOut(itemsElem, 200);
      }, 2500);
    }
    wrapper.ontouchstart = function() {
      fadeIn(itemsElem, 200);
    }
    wrapper.append(clonedElem);
    swipeWrapElem.append(wrapper);

    elem.addEventListener('click', async function (e) {
      MicroModal.show('modal');
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }

      var imgSrc = e.target.getAttribute('data-src') || e.target.getAttribute('src');
      var img = await imageLoad(imgSrc);
      clonedElem.style.width = img.width + 'px';
      clonedElem.style.height = img.height + 'px';
      
      
      mySwipe = new Swipe(mySwipeElem, {
        startSlide: idx,
        draggable: true,
        autoRestart: false,
        continuous: false,
        disableScroll: true,
        stopPropagation: true,
        callback: async function (index, element) {
          
          var imgElem = element.querySelector('img');
          var imgSrc = imgElem.getAttribute('data-src') || imgElem.getAttribute('src');
          var img = await imageLoad(imgSrc);
          imgElem.style.width = img.width + 'px';
          imgElem.style.height = img.height + 'px';

          
          if (captionElem && imgElem) {
            var caption = null;
            if (imgElem.getAttribute('data-caption')) {
              caption = imgElem.getAttribute('data-caption');
            } else if (imgElem.getAttribute('title')) {
              caption = imgElem.getAttribute('title');
            } else if (imgElem.getAttribute('alt')) {
              caption = imgElem.getAttribute('alt');
            } else {
              caption = imgElem.getAttribute('src');
            }

            captionElem.querySelector('.modal__caption--text').innerText = caption;
            pagingElem.innerText = (index + 1) + ' / ' + imgTotalNum;

            clearTimeout(myFadeTimeout);
            fadeIn(itemsElem, 200);
          }
        },
      });

      fadeIn(itemsElem);

      
      if (captionElem) {
        var caption = null;
        if (e.target.getAttribute('data-caption')) {
          caption = e.target.getAttribute('data-caption');
        } else if (e.target.getAttribute('title')) {
          caption = e.target.getAttribute('title');
        } else if (e.target.getAttribute('alt')) {
          caption = e.target.getAttribute('alt');
        } else {
          caption = e.target.getAttribute('src');
        }

        captionElem.querySelector('.modal__caption--text').innerText = caption;
        pagingElem.innerText = (idx + 1) + ' / ' + imgTotalNum;
      }

      if (normalElem && fullElem) {
        normalElem.style.zIndex = -1;
        normalElem.style.opacity = 0;
        fullElem.style.zIndex = 25;
        fullElem.style.opacity = 1;
      }
    });

    window.addEventListener('keydown', keydownFunction);
  });

  arrowLeftElem ?
    arrowLeftElem.addEventListener('click', function (e) {
      if (mySwipe) {
        mySwipe.prev();
      }
    }) : null;
  arrowRightElem ?
    arrowRightElem.addEventListener('click', function (e) {
      if (mySwipe) {
        mySwipe.next();
      }
    }) : null;

  closeElem ?
    closeElem.addEventListener('click', function () {
      if (mySwipe) {
        mySwipe.kill();
        mySwipe = null;
      }
      closeFullscreen();
      MicroModal.close('modal');
    }) : null;

  fullElem ?
    fullElem.addEventListener('click', function (e) {
      openFullscreen();
      if (normalElem) {
        normalElem.style.zIndex = 25;
        normalElem.style.opacity = 1;
        fullElem.style.zIndex = -1;
        fullElem.style.opacity = 0;
      }
    }) : null;

  normalElem ?
    normalElem.addEventListener('click', function (e) {
      closeFullscreen();
      if (fullElem) {
        fullElem.style.zIndex = 25;
        fullElem.style.opacity = 1;
        normalElem.style.zIndex = -1;
        normalElem.style.opacity = 0;
      }
    }) : null;
  
});
</script>

    <div class="hide">
      

<div class="search">
  <span class="icon">
    <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M15.5 14h-.79l-.28-.27c1.2-1.4 1.82-3.31 1.48-5.34-.47-2.78-2.79-5-5.59-5.34-4.23-.52-7.79 3.04-7.27 7.27.34 2.8 2.56 5.12 5.34 5.59 2.03.34 3.94-.28 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
  </span>
  <input id="search" aria-label="Site Search" class="input" type="text" placeholder="Search" autocomplete="off">
  <div id="search-results" class="dropdown">
    <div id="search-menu" class="dropdown-menu" role="menu">
    </div>
  </div>
</div>


    </div>
  </div>
</main>


<aside class="single__side main-side">
  


<section class="sidebar hide">
  <script>document.querySelector('.sidebar').classList.remove('hide')</script>
  <div class="toc__flexbox" data-position="absolute">
    <h6 class="toc__title" data-ani="true">What&#39;s on this Page</h6>
    
      <label class="switch" data-ani="true">
        <input id="toggle-toc" aria-label="Toggle TOC" type="checkbox" >
        <span class="slider round"></span>
      </label>
    
  </div>
  <div class="toc hide" data-dir="ltr" data-folding="true" data-ani="true">
    <nav id="TableOfContents">
  <ul>
    <li><a href="#background">Background</a></li>
    <li><a href="#一what-is-ethereum">一、What is Ethereum</a></li>
    <li><a href="#二basic-concept">二、Basic concept</a></li>
    <li><a href="#三客户端">三、客户端</a></li>
    <li><a href="#四密码学">四、密码学</a></li>
    <li><a href="#五钱包">五、钱包</a></li>
    <li><a href="#六交易">六、交易</a></li>
    <li><a href="#七solidity">七、Solidity</a></li>
    <li><a href="#八vyper">八、Vyper</a></li>
    <li><a href="#九智能合约安全">九、智能合约安全</a>
      <ul>
        <li><a href="#重入攻击">重入攻击</a></li>
        <li><a href="#整型溢出">整型溢出</a></li>
        <li><a href="#unexpected-ether">Unexpected Ether</a></li>
      </ul>
    </li>
    <li><a href="#十代币">十、代币</a></li>
    <li><a href="#十一预言机">十一、预言机</a></li>
    <li><a href="#十二dapp">十二、DAPP</a></li>
    <li><a href="#十三evm">十三、EVM</a></li>
    <li><a href="#十四consensus">十四、Consensus</a></li>
    <li><a href="#reference">Reference</a></li>
  </ul>
</nav>
  </div>
</section>



</aside>

<script>
  
  
  

  var enableToc = JSON.parse("true");
  var toc = JSON.parse("null");
  var tocPosition = JSON.parse("\"inner\"");
  
  var singleMainElem = document.querySelector('.single__main');
  var singleSideElem = document.querySelector('.single__side');

  enquire.register("screen and (max-width: 769px)", {
    match: function () {
      if ((enableToc || toc) && tocPosition !== "outer") {
        if (singleMainElem && singleSideElem) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
          singleSideElem.classList.remove('main-side');
          singleSideElem.classList.add('hide');
        }
      } else if (tocPosition === "outer") {
        if (singleMainElem && !singleMainElem.classList.contains('main-main')) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
        }
        if (singleSideElem && !singleSideElem.classList.contains('hide')) {
          singleSideElem.classList.add('hide');
        }
      }
    },
    unmatch: function () {
      if ((enableToc || toc) && tocPosition !== "outer") {
        singleMainElem.classList.remove('main');
        singleMainElem.classList.add('main-main');
        singleSideElem.classList.remove('hide');
        singleSideElem.classList.add('main-side');
      } else if (tocPosition === "outer") {
        if (singleMainElem && !singleMainElem.classList.contains('main-main')) {
          singleMainElem.classList.remove('main-main');
          singleMainElem.classList.add('main');
        }
        if (singleSideElem && !singleSideElem.classList.contains('hide')) {
          singleSideElem.classList.add('hide');
        }
      }

      var navCollapseBtn = document.querySelector('.navbar__burger');
      var navCollapse = document.getElementsByClassName('navbarm__collapse')[0];
      if (navCollapse) {
        navCollapse.setAttribute('data-open', false);
        navCollapse.style.maxHeight = 0;
        navCollapseBtn.classList.remove('is-active');
      }
      document.getElementsByClassName('navbar__menu')[0].classList.remove('is-active');
      document.getElementsByClassName('mobile-search')[0].classList.add('hide');
    },
    setup: function () { },
    deferSetup: true,
    destroy: function () { },
  });
</script>





<script defer src="/js/helper/getParents.min.js"></script>

<script defer src="/js/helper/closest.min.js"></script>

<script defer src="/js/helper/prev.min.js"></script>

<script defer src="/js/helper/prop.min.js"></script>

<script defer src="/js/helper/fadeinout.min.js"></script>

<script defer src="/js/helper/throttle.min.js"></script>






































  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css" integrity="sha256-V8SV2MO1FUb63Bwht5Wx9x6PVHNa02gv8BgH/uH3ung=" crossorigin="anonymous">
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js" integrity="sha256-F/Xda58SPdcUCr&#43;xhSGz9MA2zQBPb0ASEYKohl8UCHc=" crossorigin="anonymous"></script>
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/contrib/auto-render.min.js" integrity="sha256-90d2pnfw0r4K8CZAWPko4rpFXQsZvJhTBGYNkipDprI=" crossorigin="anonymous"></script>














<script>
  'use strict';

  window.onload = function() {
    var navbar = document.querySelector('.navbar');
    var singleContentsElem = document.querySelector('.single__contents');

    
    
    
    var enableBusuanzi = JSON.parse("true");
    var busuanziPagePV = JSON.parse("true");
    
    if (enableBusuanzi && busuanziPagePV) {
      var pagePvElem = document.querySelector('#busuanzi_value_page_pv');
      pagePvElem.textContent = pagePvElem.textContent.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
    }    
    



    
    
    
    
    
    
    var enableToc = JSON.parse("true");
    var toc = JSON.parse("null");
    var hideToc = JSON.parse("true");
    var tocFlexbox = document.querySelector('.toc__flexbox');
    var tocFlexboxOuter = document.querySelector('.toc__flexbox--outer');
    var tocFolding = JSON.parse("true");
    
    if ((enableToc || toc) && document.querySelector('.toc')) {
      var tableOfContentsElem = document.querySelector('.toc').querySelector('#TableOfContents');

      tableOfContentsElem.onmouseenter = function() {
        if (navbar.classList.contains('scrolling')) {
          navbar.classList.remove('scrolling');
        }
      }

      tableOfContentsElem.onmouseleave = function() {
        if (!navbar.classList.contains('scrolling')) {
          navbar.classList.add('scrolling');
        }
      }

      if (false === tocFolding) {

      } else {
        tableOfContentsElem.querySelectorAll('ul') ?
          tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
            rootUl.querySelectorAll('li').forEach(function (liElem) {
              liElem.querySelectorAll('ul').forEach(function (ulElem) {
                ulElem.style.display = 'none';
              });
            });
          }) : null;
      }

      if (tableOfContentsElem) {
        if (tableOfContentsElem.querySelectorAll('a').length > 0) {
          tableOfContentsElem.querySelectorAll('a').forEach(function (elem) {
            elem.addEventListener('click', function () {
              var id = elem.getAttribute('id');

              if (!navbar.classList.contains('scrolling')) {
                navbar.classList.remove('navbar--show');
                navbar.classList.remove('navbar--hide');
                navbar.classList.add('navbar--hide');
              }
              
              document.querySelector('.toc').querySelectorAll('a').forEach(function (elem) {
                elem.classList.remove('active');
              });
              elem.classList.add('active');

              var curElem = tableOfContentsElem.querySelector('[href="#' + id + '"]');
              if (curElem && curElem.nextElementSibling) {
                curElem.nextElementSibling.style.display = 'block';
              }
              if (curElem) {
                getParents(curElem, 'ul') ?
                  getParents(curElem, 'ul').forEach(function (elem) {
                    elem.style.display = 'block';
                  }) : null;
              }
            });
          });
        } else {
          if (tocFlexbox) {
            tocFlexbox.setAttribute('data-position', '');
            if (!tocFlexbox.classList.contains('hide')) {
              tocFlexbox.classList.add('hide');
            }
          }
          if (tocFlexboxOuter) {
            tocFlexboxOuter.setAttribute('data-position', '');
            if (!tocFlexboxOuter.classList.contains('hide')) {
              tocFlexboxOuter.classList.add('hide');
            }
          }
        }
      }

      
      var toggleTocElem = document.getElementById("toggle-toc");
      var visibleTocElem = document.getElementById('visible-toc');
      var tocElem = document.querySelector('.toc');
      var mainElem = document.querySelector('main');
      var sideElem = document.querySelector('side');
      var tocFlexboxElem = document.querySelector('.toc__flexbox');

      toggleTocElem ? 
      toggleTocElem.addEventListener('change', function(e) {
        if (e.target.checked) {
          if (tocElem) {
            fadeIn(tocElem, 200);
          }
          if (tocFlexboxElem) {
            tocFlexboxElem.setAttribute('data-position', 'fixed');
          }

          if (mainElem) {
            mainElem.classList.remove('main-main');
            mainElem.classList.remove('main');
            mainElem.classList.add('main-main');
          }
          if (sideElem) {
            sideElem.classList.remove('main-side');
          }
        } else {
          if (tocElem) {
            fadeOut(tocElem, 200);
          }
          if (tocFlexboxElem) {
            tocFlexboxElem.setAttribute('data-position', 'absolute');
          }

          if (mainElem) {
            mainElem.classList.remove('main-main');
            mainElem.classList.remove('main');
            mainElem.classList.add('main');
          }
          if (sideElem) {
            sideElem.classList.remove('main-side');
          }
        }
      }) : null;

      visibleTocElem ?
      visibleTocElem.addEventListener('change', function(e) {
        if (e.target.checked) {
          if (tocElem) {
            fadeIn(tocElem, 200);
          }
        } else {
          if (tocElem) {
            fadeOut(tocElem, 200);
          }
        }
      }) : null;
    }
    
    
    
    
    
    var topOffset = 120;
    var botOffset = 70;
    var handleWindowResize = function () {
      if (tocElem) {
        tocElem.style.maxHeight = (window.innerHeight - topOffset - botOffset) + 'px';
      }
    }
    var throttledWindowResize = throttle(handleWindowResize, 300);
    throttledWindowResize()

    
    window.addEventListener('resize', throttledWindowResize);
    



    
    var text, clip = new ClipboardJS('.anchor');
    var headers = singleContentsElem.querySelectorAll("h1, h2, h3, h4");

    
    var languagedir = JSON.parse("\"ltr\"");

    headers ? 
    headers.forEach(function (elem) {
      var size = parseInt(elem.tagName.substr(1), 10) * 2;
      var url = encodeURI(document.location.origin + document.location.pathname);
      var link = url + "#" + elem.getAttribute('id');
      var newElemOuter = document.createElement('span');
      newElemOuter.classList.add('anchor');
      newElemOuter.classList.add('hide');
      newElemOuter.setAttribute('data-clipboard-text', decodeURI(link));
      newElemOuter.style.position = 'relative';

      var newElemInner = document.createElement('span');
      newElemInner.style.position = 'absolute';
      newElemInner.style.top = '50%';
      newElemInner.style.left = '0.75rem';
      newElemInner.style.transform = 'translateY(-50%)';
      newElemInner.innerHTML = `
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="${32 - size}px" height="${32 - size}px"><path d="M 5.5625 0 C 4.136719 0 2.707031 0.542969 1.625 1.625 C -0.539063 3.789063 -0.539063 7.335938 1.625 9.5 L 5.28125 13.15625 C 5.667969 13.554688 6.304688 13.558594 6.703125 13.171875 C 7.101563 12.785156 7.105469 12.148438 6.71875 11.75 L 3.03125 8.0625 C 1.632813 6.664063 1.632813 4.429688 3.03125 3.03125 C 4.429688 1.632813 6.664063 1.632813 8.0625 3.03125 L 12.96875 7.9375 C 14.367188 9.335938 14.367188 11.570313 12.96875 12.96875 C 12.804688 13.132813 12.621094 13.25 12.4375 13.375 C 11.980469 13.6875 11.859375 14.308594 12.171875 14.765625 C 12.484375 15.222656 13.105469 15.34375 13.5625 15.03125 C 13.847656 14.835938 14.125 14.625 14.375 14.375 C 16.539063 12.210938 16.539063 8.664063 14.375 6.5 L 9.5 1.625 C 8.417969 0.542969 6.988281 0 5.5625 0 Z M 10.78125 8.875 C 10.738281 8.882813 10.695313 8.894531 10.65625 8.90625 C 10.507813 8.9375 10.371094 9 10.25 9.09375 C 10.039063 9.253906 9.820313 9.429688 9.625 9.625 C 7.460938 11.789063 7.460938 15.335938 9.625 17.5 L 14.5 22.375 C 16.664063 24.539063 20.210938 24.539063 22.375 22.375 C 24.539063 20.210938 24.539063 16.664063 22.375 14.5 L 18.71875 10.875 C 18.476563 10.578125 18.089844 10.441406 17.714844 10.527344 C 17.34375 10.613281 17.050781 10.90625 16.964844 11.277344 C 16.878906 11.652344 17.015625 12.039063 17.3125 12.28125 L 20.96875 15.9375 C 22.367188 17.335938 22.367188 19.570313 20.96875 20.96875 C 19.570313 22.367188 17.335938 22.367188 15.9375 20.96875 L 11.03125 16.0625 C 9.632813 14.664063 9.632813 12.429688 11.03125 11.03125 C 11.152344 10.90625 11.300781 10.820313 11.4375 10.71875 C 11.839844 10.472656 12.015625 9.976563 11.855469 9.53125 C 11.699219 9.085938 11.25 8.8125 10.78125 8.875 Z"/></svg>`;

      if (languagedir === "rtl") {
        newElemInner.style.left = '-2rem';
      } else {
        newElemInner.style.right = '-2rem';
      }

      newElemOuter.append(newElemInner);
      elem.append(newElemOuter);

      elem.addEventListener('mouseenter', function() {
        this.querySelector('.anchor').classList.remove('hide');
      });
      elem.addEventListener('mouseleave', function () {
        this.querySelector('.anchor').classList.add('hide');
      });
    }) : null;

    document.querySelectorAll('.anchor').forEach(function(elem) {
      elem.addEventListener('mouseleave', function() {
        elem.setAttribute('aria-label', null);
        elem.classList.remove('tooltipped');
        elem.classList.remove('tooltipped-s');
        elem.classList.remove('tooltipped-w');
      });
    });

    clip.on('success', function (e) {
      e.clearSelection();
      e.trigger.setAttribute('aria-label', 'Link copied to clipboard!');
      e.trigger.classList.add('tooltipped');
      e.trigger.classList.add('tooltipped-s');
    });
    // =================================================================



    
    
    var lib = JSON.parse("[\"katex\"]");

    if (lib && lib.includes('mermaid')) {
      
      var themeVariant = localStorage.getItem('theme') || JSON.parse("\"dark\"");

      if (themeVariant === "dark" || themeVariant === "hacker") {
        mermaid.initialize({ theme: 'dark' });
      } else {
        mermaid.initialize({ theme: 'default' });
      }
      
      var mermaids = [];
      [].push.apply(mermaids, document.getElementsByClassName('language-mermaid'));
      mermaids.forEach(function(elem) {
        var elemParentNode = elem.parentNode;

        if (elemParentNode !== document.body) {
          elemParentNode.parentNode.insertBefore(elem, elemParentNode);
          elemParentNode.parentNode.removeChild(elemParentNode);
        }

        var newElemWrapper = document.createElement('div');
        newElemWrapper.classList.add('mermaid');
        newElemWrapper.style.padding = '34px 4px 6px';
        newElemWrapper.innerHTML = elem.innerHTML;
        elem.replaceWith(newElemWrapper);
      });
    }
    

    

    
    if (lib && lib.includes('katex')) {
      var mathElements = document.getElementsByClassName('math');
      var options = {
        delimiters: [
          { left: "$$", right: "$$", display: true },
          { left: "\\[", right: "\\]", display: true },
          { left: "$", right: "$", display: false },
          { left: "\\(", right: "\\)", display: false }
        ],
      };

      renderMathInElement(document.querySelector('.single__contents'), options);
    }
    



    
    if (lib && lib.includes('flowchartjs')) {
      
      var options = JSON.parse("{\"arrow-end\":\"block\",\"element-color\":\"black\",\"fill\":\"white\",\"flowstate\":{\"approved\":{\"fill\":\"#58C4A3\",\"font-size\":12,\"no-text\":\"n/a\",\"yes-text\":\"APPROVED\"},\"current\":{\"fill\":\"yellow\",\"font-color\":\"red\",\"font-weight\":\"bold\"},\"future\":{\"fill\":\"#FFFF99\"},\"invalid\":{\"fill\":\"#444444\"},\"past\":{\"fill\":\"#CCCCCC\",\"font-size\":12},\"rejected\":{\"fill\":\"#C45879\",\"font-size\":12,\"no-text\":\"REJECTED\",\"yes-text\":\"n/a\"},\"request\":{\"fill\":\"blue\"}},\"font-color\":\"black\",\"font-size\":14,\"line-color\":\"black\",\"line-length\":50,\"line-width\":3,\"no-text\":\"no\",\"scale\":1,\"symbols\":{\"end\":{\"class\":\"end-element\"},\"start\":{\"element-color\":\"green\",\"fill\":\"yellow\",\"font-color\":\"red\"}},\"text-margin\":10,\"x\":0,\"y\":0,\"yes-text\":\"yes\"}");
      var jsonContent = null;

      var flowchartPrefix = "language-flowchart";
      var index = 0;
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + flowchartPrefix + "]"), function(x){
          x.style.display = 'none'
          x.parentNode.style.backgroundColor = "transparent"
          jsonContent = x.innerText;

          var node0 = document.createElement('div');
          node0.id = 'flowchart' + index;
          x.parentNode.insertBefore(node0, x);

          var diagram = flowchart.parse(jsonContent);
          diagram.drawSVG("flowchart"+index, options);

          index +=1;
      });      
    }
    

    

    
    document.querySelectorAll("mjx-container").forEach(function (x) {
      x.parentElement.classList += 'has-jax'
    });
    



    
    if (lib && lib.includes('msc')) {
      
      var options = JSON.parse("{\"theme\":\"hand\"}");
      var jsonContent = null;

      var index = 0;
      var chartPrefix = "language-msc";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('div');
        node0.id = 'msc' + index;
        x.parentNode.insertBefore(node0, x);
        var diagram = Diagram.parse(jsonContent);
        diagram.drawSVG("msc" + index, options);
        index += 1;
      });
    }
    



    
    if (lib && lib.includes('chart')) {
      var borderColor = "#666";
      var bgColor = "#ddd";
      var borderWidth = 2;

      Chart.defaults.global.elements.rectangle.borderWidth = borderWidth;
      Chart.defaults.global.elements.rectangle.borderColor = borderColor;
      Chart.defaults.global.elements.rectangle.backgroundColor = bgColor;

      Chart.defaults.global.elements.line.borderWidth = borderWidth;
      Chart.defaults.global.elements.line.borderColor = borderColor;
      Chart.defaults.global.elements.line.backgroundColor = bgColor;

      Chart.defaults.global.elements.point.borderWidth = borderWidth;
      Chart.defaults.global.elements.point.borderColor = borderColor;
      Chart.defaults.global.elements.point.backgroundColor = bgColor;

      var chartPrefix = "language-chart";
      var index = 0;
      var jsonContent = null;

      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + chartPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('canvas');
        var source = null;
        node0.height = 200;
        node0.style.height = 200;
        node0.id = 'myChart' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        var ctx = document.getElementById('myChart' + index).getContext('2d');
        var myChart = new Chart(ctx, source);
        index += 1;
      });            
    }
    



    
    if (lib && lib.includes('wavedrom')) {
      var wavePrefix = "language-wave";
      var index = 0;
      var jsonContent = null;
      
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + wavePrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        jsonContent = x.innerText;
        var node0 = document.createElement('div');
        var source = null;
        node0.id = 'WaveDrom_Display_' + index;
        source = JSON.parse(jsonContent);
        x.parentNode.insertBefore(node0, x);
        WaveDrom.RenderWaveForm(index, source, "WaveDrom_Display_");
        index += 1;
      });
    }
    



    
    if (lib && lib.includes('viz')) {
      var vizPrefix = "language-viz-";
      Array.prototype.forEach.call(document.querySelectorAll("[class^=" + vizPrefix + "]"), function (x) {
        x.style.display = 'none'
        x.parentNode.style.backgroundColor = "transparent"
        var engine;
        x.getAttribute("class").split(" ").forEach(function (cls) {
          if (cls.startsWith(vizPrefix)) {
            engine = cls.substr(vizPrefix.length);
          }
        });
        var viz = new Viz();
        viz.renderSVGElement(x.innerText, { engine: engine })
          .then(function (element) {
            element.style.width = "100%";
            x.parentNode.insertBefore(element, x);
          })
      });
    }
    
    
  }
</script>


            
            <footer class="footer">
    
<div class="dropdown">
  <button class="dropdown-trigger" aria-label="Select Language Button">
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="currentColor" d="M12.65 15.67c.14-.36.05-.77-.23-1.05l-2.09-2.06.03-.03c1.74-1.94 2.98-4.17 3.71-6.53h1.94c.54 0 .99-.45.99-.99v-.02c0-.54-.45-.99-.99-.99H10V3c0-.55-.45-1-1-1s-1 .45-1 1v1H1.99c-.54 0-.99.45-.99.99 0 .55.45.99.99.99h10.18C11.5 7.92 10.44 9.75 9 11.35c-.81-.89-1.49-1.86-2.06-2.88-.16-.29-.45-.47-.78-.47-.69 0-1.13.75-.79 1.35.63 1.13 1.4 2.21 2.3 3.21L3.3 16.87c-.4.39-.4 1.03 0 1.42.39.39 1.02.39 1.42 0L9 14l2.02 2.02c.51.51 1.38.32 1.63-.35zM17.5 10c-.6 0-1.14.37-1.35.94l-3.67 9.8c-.24.61.22 1.26.87 1.26.39 0 .74-.24.88-.61l.89-2.39h4.75l.9 2.39c.14.36.49.61.88.61.65 0 1.11-.65.88-1.26l-3.67-9.8c-.22-.57-.76-.94-1.36-.94zm-1.62 7l1.62-4.33L19.12 17h-3.24z"/></svg>
  </button>
  <div class="dropdown-content">
    
    
    
  </div>
</div>

    
    
<div id="gtt">
  <div class="gtt">
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M8.12 14.71L12 10.83l3.88 3.88c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L12.7 8.71c-.39-.39-1.02-.39-1.41 0L6.7 13.3c-.39.39-.39 1.02 0 1.41.39.38 1.03.39 1.42 0z"/></svg>
  </div>
</div>

    <hr />

    <div class="basicflex flexwrap">
        
            
        
            
        
    </div>

    <div class="footer__poweredby">
        
  <div class="busuanzi">
    
    
      <div class="busuanzi__item">
        <span class="busuanzi__item--label">
          Total visitors
        </span>
        <span id="busuanzi_value_site_uv" class="busuanzi__item--number">...</span>
      </div>
    

    
      <div class="busuanzi__item">
        <span class="busuanzi__item--label">
          Total views
        </span>
        <span id="busuanzi_value_site_pv" class="busuanzi__item--number">...</span>
      </div>
    

  </div>

                
            <p class="caption">
                
                    ©2023, All Rights Reserved
                
            </p>
        

        
        
    </div> 
</footer>
        </div>
        





<div class="wrapper__right hide" data-pad="true" dir="ltr">
  <script>document.querySelector('.wrapper__right').classList.remove('hide')</script>
  
</div>

    </div>
</body>

</html>